aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/filectrl.test12
-rw-r--r--test/lock_common.tcl1
-rw-r--r--test/shell1.test13
-rw-r--r--test/tester.tcl5
-rw-r--r--test/testrunner_data.tcl7
-rw-r--r--test/walsetlk.test158
-rw-r--r--test/walsetlk2.test260
-rw-r--r--test/walsetlk3.test135
-rw-r--r--test/win32longpath.test7
9 files changed, 584 insertions, 14 deletions
diff --git a/test/filectrl.test b/test/filectrl.test
index 460b71e25..fee29e044 100644
--- a/test/filectrl.test
+++ b/test/filectrl.test
@@ -36,11 +36,13 @@ do_test filectrl-1.5 {
sqlite3 db test_control_lockproxy.db
file_control_lockproxy_test db [get_pwd]
} {}
-do_test filectrl-1.6 {
- sqlite3 db test.db
- set fn [file_control_tempfilename db]
- set fn
-} {/etilqs_/}
+ifcapable !winrt {
+ do_test filectrl-1.6 {
+ sqlite3 db test.db
+ set fn [file_control_tempfilename db]
+ set fn
+ } {/etilqs_/}
+}
db close
forcedelete .test_control_lockproxy.db-conch test.proxy
forcedelete test.db test2.db
diff --git a/test/lock_common.tcl b/test/lock_common.tcl
index 3e1821bab..9504a8c04 100644
--- a/test/lock_common.tcl
+++ b/test/lock_common.tcl
@@ -145,6 +145,7 @@ proc testfixture_nb_cb {varname chan} {
}
if { $line == "OVER" } {
+ global $varname
set $varname [lindex $::tfnb($chan) 1]
unset ::tfnb($chan)
close $chan
diff --git a/test/shell1.test b/test/shell1.test
index a272295f5..722418c7a 100644
--- a/test/shell1.test
+++ b/test/shell1.test
@@ -296,7 +296,9 @@ do_test shell1-3.2.4 {
catchcmd "test.db" ".bail OFF BAD"
} {1 {Usage: .bail on|off}}
-ifcapable vtab {
+# This test will not work on winrt, as winrt has no concept of the absolute
+# paths that the test expects in the result. It uses relative paths only.
+ifcapable vtab&&!winrt {
# .databases List names and files of attached databases
do_test shell1-3.3.1 {
catchcmd "-csv test.db" ".databases"
@@ -744,9 +746,12 @@ do_test shell1-3.26.6 {
do_test shell1-3.27.1 {
catchcmd "test.db" ".timer"
} {1 {Usage: .timer on|off}}
-do_test shell1-3.27.2 {
- catchcmd "test.db" ".timer ON"
-} {0 {}}
+ifcapable !winrt {
+ # No timer support on winrt.
+ do_test shell1-3.27.2 {
+ catchcmd "test.db" ".timer ON"
+ } {0 {}}
+}
do_test shell1-3.27.3 {
catchcmd "test.db" ".timer OFF"
} {0 {}}
diff --git a/test/tester.tcl b/test/tester.tcl
index b5f49ebde..079255761 100644
--- a/test/tester.tcl
+++ b/test/tester.tcl
@@ -1776,6 +1776,11 @@ proc crashsql {args} {
# cfSync(), which can be different then what TCL uses by
# default, so here we force it to the "nativename" format.
set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]]
+ ifcapable winrt {
+ # Except on winrt. Winrt has no way to transform a relative path into
+ # an absolute one, so it just uses the relative paths.
+ set cfile $crashfile
+ }
set f [open crash.tcl w]
puts $f "sqlite3_initialize ; sqlite3_shutdown"
diff --git a/test/testrunner_data.tcl b/test/testrunner_data.tcl
index 2cfa7f3b3..4685dabf5 100644
--- a/test/testrunner_data.tcl
+++ b/test/testrunner_data.tcl
@@ -37,6 +37,7 @@ namespace eval trd {
set tcltest(win.Windows-Memdebug) veryquick
set tcltest(win.Windows-Win32Heap) veryquick
set tcltest(win.Windows-Sanitize) veryquick
+ set tcltest(win.Windows-WinRT) veryquick
set tcltest(win.Default) full
# Extra [make xyz] tests that should be run for various builds.
@@ -358,11 +359,17 @@ namespace eval trd {
set build(Windows-Win32Heap) {
WIN32HEAP=1
DEBUG=4
+ ENABLE_SETLK=1
}
set build(Windows-Sanitize) {
ASAN=1
}
+ set build(Windows-WinRT) {
+ FOR_WINRT=1
+ ENABLE_SETLK=1
+ -DSQLITE_TEMP_STORE=3
+ }
}
diff --git a/test/walsetlk.test b/test/walsetlk.test
index 1e0923822..d3fd050a6 100644
--- a/test/walsetlk.test
+++ b/test/walsetlk.test
@@ -80,6 +80,19 @@ db2 close
#-------------------------------------------------------------------------
do_multiclient_test tn {
+
+ testvfs tvfs -fullshm 1
+ db close
+ sqlite3 db test.db -vfs tvfs
+ tvfs script xSleep_callback
+ tvfs filter xSleep
+
+ set ::sleep_count 0
+ proc xSleep_callback {xSleep nMs} {
+ after [expr $nMs / 1000]
+ incr ::sleep_count
+ }
+
do_test 2.$tn.1 {
sql1 {
PRAGMA journal_mode = wal;
@@ -132,7 +145,6 @@ do_multiclient_test tn {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
-
do_test 2.$tn.9 {
sql3 {
INSERT INTO t1 VALUES(11, 12);
@@ -178,13 +190,50 @@ do_multiclient_test tn {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
-
+
+ db close
+ tvfs delete
+
+ # Set bSleep to true if it is expected that the above used xSleep() to
+ # wait for locks. bSleep is true unless SQLITE_ENABLE_SETLK_TIMEOUT is
+ # set to 1 and either:
+ #
+ # * the OS is windows, or
+ # * the OS is unix and the tests were run with each connection
+ # in a separate process.
+ #
+ set bSleep 1
+ if {$::sqlite_options(setlk_timeout)==1} {
+ if {$::tcl_platform(platform)=="windows"} {
+ set bSleep 0
+ }
+ if {$::tcl_platform(platform)=="unix"} {
+ set bSleep [expr $tn==2]
+ }
+ }
+
+ do_test 2.$tn.15.$bSleep {
+ expr $::sleep_count > 0
+ } $bSleep
}
#-------------------------------------------------------------------------
reset_db
-sqlite3 db2 test.db
+
+testvfs tvfs -fullshm 1
+tvfs script xSleep_callback
+tvfs filter xSleep
+
+set ::sleep_count 0
+proc xSleep_callback {xSleep nMs} {
+ after [expr $nMs / 1000]
+ incr ::sleep_count
+ breakpoint
+}
+
+sqlite3 db2 test.db -vfs tvfs
db2 timeout 1000
+
do_execsql_test 3.0 {
PRAGMA journal_mode = wal;
CREATE TABLE x1(x, y);
@@ -192,8 +241,109 @@ do_execsql_test 3.0 {
INSERT INTO x1 VALUES(1, 2);
} {wal}
-do_test 3.1 {
+do_execsql_test -db db2 3.1a {
+ SELECT * FROM x1
+} {}
+
+do_test 3.1b {
list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg
} {1 {database is locked}}
+# Set bExpect to true if calls to xSleep() are expected. Such calls are
+# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
+set bExpect 1
+if {$tcl_platform(platform)=="windows" && $::sqlite_options(setlk_timeout)==1} {
+ set bExpect 0
+}
+do_test 3.2 {
+ expr {$::sleep_count > 0}
+} $bExpect
+set ::sleep_count 0
+
+do_execsql_test 3.3 {
+ COMMIT;
+}
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO x1 VALUES(3, 4);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+}
+
+after 500 {set ok 1}
+vwait ok
+
+db2 timeout 5000
+do_test 3.4 {
+ set t [lindex [time { db2 eval { BEGIN EXCLUSIVE } }] 0]
+ expr ($t>1000000)
+} {1}
+
+# Set bExpect to true if calls to xSleep() are expected. Such calls are
+# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
+set bExpect 1
+if {$::sqlite_options(setlk_timeout)==1} {
+ set bExpect 0
+}
+do_test 3.5 {
+ expr {$::sleep_count > 0}
+} $bExpect
+
+do_execsql_test -db db2 3.6 {
+ INSERT INTO x1 VALUES(5, 6);
+ COMMIT;
+ SELECT * FROM x1;
+} {1 2 3 4 5 6}
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO x1 VALUES(7, 8);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+}
+
+after 500 {set ok 1}
+vwait ok
+
+db2 timeout 0x7FFFFFFF
+do_test 3.7 {
+ set t [lindex [time { db2 eval { BEGIN EXCLUSIVE } }] 0]
+ expr ($t>1000000)
+} {1}
+
+# Set bExpect to true if calls to xSleep() are expected. Such calls are
+# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
+set bExpect 1
+if {$::sqlite_options(setlk_timeout)==1} {
+ set bExpect 0
+}
+do_test 3.8 {
+ expr {$::sleep_count > 0}
+} $bExpect
+
+do_execsql_test -db db2 3.9 {
+ INSERT INTO x1 VALUES(9, 10);
+ COMMIT;
+ SELECT * FROM x1;
+} {1 2 3 4 5 6 7 8 9 10}
+
+db2 close
+tvfs delete
+
finish_test
+
diff --git a/test/walsetlk2.test b/test/walsetlk2.test
new file mode 100644
index 000000000..7fadc97fb
--- /dev/null
+++ b/test/walsetlk2.test
@@ -0,0 +1,260 @@
+# 2025 Jan 24
+#
+# 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.
+#
+#***********************************************************************
+#
+# TESTRUNNER: slow
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+set testprefix walsetlk2
+
+ifcapable !wal {finish_test ; return }
+ifcapable !setlk_timeout {finish_test ; return }
+
+#-------------------------------------------------------------------------
+# Check that xShmLock calls are as expected for write transactions in
+# setlk mode.
+#
+reset_db
+
+do_execsql_test 1.0 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES(1, 2, 3);
+} {wal}
+db close
+
+testvfs tvfs
+tvfs script xShmLock_callback
+tvfs filter xShmLock
+
+set ::xshmlock [list]
+proc xShmLock_callback {method path name detail} {
+ lappend ::xshmlock $detail
+}
+
+sqlite3 db test.db -vfs tvfs
+db timeout 1000
+
+do_execsql_test 1.1 {
+ SELECT * FROM t1
+} {1 2 3}
+
+do_execsql_test 1.2 {
+ INSERT INTO t1 VALUES(4, 5, 6);
+}
+
+set ::xshmlock [list]
+do_execsql_test 1.3 {
+ INSERT INTO t1 VALUES(7, 8, 9);
+}
+
+do_test 1.4 {
+ set ::xshmlock
+} [list \
+ {0 1 lock exclusive} \
+ {4 1 lock exclusive} {4 1 unlock exclusive} \
+ {4 1 lock shared} \
+ {0 1 unlock exclusive} \
+ {4 1 unlock shared}
+]
+
+do_execsql_test 1.5.1 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8 9}
+set ::xshmlock [list]
+do_execsql_test 1.5.2 {
+ INSERT INTO t1 VALUES(10, 11, 12);
+}
+do_test 1.5.3 {
+ set ::xshmlock
+} [list \
+ {0 1 lock exclusive} \
+ {4 1 lock shared} \
+ {0 1 unlock exclusive} \
+ {4 1 unlock shared}
+]
+
+db close
+tvfs delete
+
+#-------------------------------------------------------------------------
+# Check that if sqlite3_setlk_timeout() is used, blocking locks timeout
+# but other operations do not use the retry mechanism.
+#
+reset_db
+
+do_execsql_test 2.0 {
+ CREATE TABLE t1(a, b);
+ INSERT INTO t1 VALUES(1, 2), (3, 4);
+}
+
+sqlite3_setlk_timeout db 2000
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(5, 6);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 2.1 {
+ INSERT INTO t1 VALUES(7, 8);
+} {1 {database is locked}}
+
+sqlite3_busy_timeout db 2000
+
+do_catchsql_test 2.2 {
+ INSERT INTO t1 VALUES(7, 8);
+} {0 {}}
+
+do_execsql_test 2.3 {
+ SELECT * FROM t1
+} {1 2 3 4 5 6 7 8}
+
+do_execsql_test 2.4 {
+ PRAGMA journal_mode = wal;
+} {wal}
+
+db close
+sqlite3 db test.db
+
+do_execsql_test 2.5 {
+ INSERT INTO t1 VALUES(9, 10);
+}
+
+sqlite3_setlk_timeout db 2000
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(11, 12);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 2.6 {
+ INSERT INTO t1 VALUES(13, 14);
+} {0 {}}
+
+do_execsql_test 2.7 {
+ SELECT * FROM t1
+} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
+
+#-------------------------------------------------------------------------
+# Check that if sqlite3_setlk_timeout(-1) is called, blocking locks are
+# enabled and last for a few seconds at least. Difficult to test that they
+# really do block indefinitely.
+#
+reset_db
+
+do_execsql_test 3.0 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t1 VALUES(1, 'one'), (3, 'three');
+} {wal}
+
+sqlite3_setlk_timeout db -1
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(5, 'five');
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+breakpoint
+do_catchsql_test 3.1 {
+ INSERT INTO t1 VALUES(7, 'seven');
+} {0 {}}
+
+# Launch another non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(9, 'nine');
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 3.2 {
+ INSERT INTO t1 VALUES(9, 'ten');
+} {1 {UNIQUE constraint failed: t1.a}}
+
+do_execsql_test 3.3 {
+ SELECT * FROM t1
+} {1 one 3 three 5 five 7 seven 9 nine}
+
+db close
+
+# Launch another non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(11, 'eleven');
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+}
+
+sqlite3 db test.db
+sqlite3_setlk_timeout db -1
+do_catchsql_test 3.4 {
+ INSERT INTO t1 VALUES(13, 'thirteen');
+} {0 {}}
+
+
+finish_test
+
diff --git a/test/walsetlk3.test b/test/walsetlk3.test
new file mode 100644
index 000000000..b091b183d
--- /dev/null
+++ b/test/walsetlk3.test
@@ -0,0 +1,135 @@
+# 2020 May 06
+#
+# 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.
+#
+#***********************************************************************
+#
+# TESTRUNNER: slow
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+set testprefix walsetlk3
+
+ifcapable !wal {finish_test ; return }
+ifcapable !setlk_timeout {finish_test ; return }
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(x, y);
+ PRAGMA journal_mode = wal;
+ INSERT INTO t1 VALUES(1, 2);
+ INSERT INTO t1 VALUES(3, 4);
+} {wal}
+
+db close
+
+proc sql_block_on_close {sql} {
+ testfixture_nb done [string map [list %SQL% $sql] {
+ testvfs tvfs
+ tvfs script xWrite
+ tvfs filter xWrite
+
+ set ::delay_done 0
+ proc xWrite {method fname args} {
+ if {[file tail $fname]=="test.db" && $::delay_done==0} {
+ after 3000
+ set ::delay_done 1
+ }
+ return 0
+ }
+
+ sqlite3 db test.db -vfs tvfs
+ db eval {%SQL%}
+ db close
+ }]
+}
+
+# Start a second process that writes to the db, then blocks within the
+# [db close] holding an EXCLUSIVE on the db in order to checkpoint and
+# delete the wal file. Then try to read the db.
+#
+# Without the SQLITE_SETLK_BLOCK_ON_CONNECT flag, this should fail with
+# SQLITE_BUSY.
+#
+sql_block_on_close {
+ INSERT INTO t1 VALUES(5, 6);
+ INSERT INTO t1 VALUES(7, 8);
+}
+after 500 {set ok 1}
+vwait ok
+sqlite3 db test.db
+sqlite3_setlk_timeout db 2000
+do_catchsql_test 1.1 {
+ SELECT * FROM t1
+} {1 {database is locked}}
+
+vwait ::done
+
+# But with SQLITE_SETLK_BLOCK_ON_CONNECT flag, it should succeed.
+#
+sql_block_on_close {
+ INSERT INTO t1 VALUES(9, 10);
+ INSERT INTO t1 VALUES(11, 12);
+}
+after 500 {set ok 1}
+vwait ok
+sqlite3 db test.db
+sqlite3_setlk_timeout -block db 2000
+do_catchsql_test 1.2 {
+ SELECT * FROM t1
+} {0 {1 2 3 4 5 6 7 8 9 10 11 12}}
+
+vwait ::done
+
+#-------------------------------------------------------------------------
+# Check that the SQLITE_SETLK_BLOCK_ON_CONNECT does not cause connections
+# to block when taking a SHARED lock on a rollback mode database.
+#
+reset_db
+do_execsql_test 2.1 {
+ CREATE TABLE x1(a);
+ INSERT INTO x1 VALUES(1), (2), (3);
+}
+
+proc sql_block_on_write {sql} {
+ testfixture_nb done [string map [list %SQL% $sql] {
+ sqlite3 db test.db
+ db eval "BEGIN EXCLUSIVE"
+ db eval {%SQL%}
+ after 3000
+ db eval COMMIT
+ db close
+ }]
+}
+
+db close
+sql_block_on_write {
+ INSERT INTO x1 VALUES(4);
+}
+
+after 500 {set ok 1}
+vwait ok
+
+sqlite3 db test.db
+sqlite3_setlk_timeout -block db 2000
+
+do_catchsql_test 2.2 {
+ SELECT * FROM x1
+} {1 {database is locked}}
+
+vwait ::done
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 2.3 {
+ SELECT * FROM x1
+} {0 {1 2 3 4}}
+
+finish_test
+
diff --git a/test/win32longpath.test b/test/win32longpath.test
index 9ffea775e..b948de79f 100644
--- a/test/win32longpath.test
+++ b/test/win32longpath.test
@@ -115,7 +115,12 @@ do_test 1.6 {
db3 close
-foreach tn {1a 1b 1c 1d 1e 1f} {
+# winrt platforms do not handle paths with unix-style '/' directory separators.
+#
+set lUri [list 1a 1b 1c 1d 1e 1f]
+ifcapable winrt { set lUri [list 1a 1c 1e] }
+
+foreach tn $lUri {
sqlite3 db3 $uri($tn) -vfs win32-longpath -uri 1 -translatefilename 0
do_test 1.7.$tn {