1#
2# 2003 December 18
3#
4# The author disclaims copyright to this source code.  In place of
5# a legal notice, here is a blessing:
6#
7#    May you do good and not evil.
8#    May you find forgiveness for yourself and forgive others.
9#    May you share freely, never taking more than you give.
10#
11#***********************************************************************
12# This file implements regression tests for SQLite library.  The
13# focus of this script is multithreading behavior
14#
15# $Id: thread1.test,v 1.3 2004/02/11 02:18:07 drh Exp $
16
17
18set testdir [file dirname $argv0]
19source $testdir/tester.tcl
20
21# Skip this whole file if the thread testing code is not enabled
22#
23if {[llength [info command thread_step]]==0 || [sqlite -has-codec]} {
24  finish_test
25  return
26}
27
28# Create some data to work with
29#
30do_test thread1-1.1 {
31  execsql {
32    CREATE TABLE t1(a,b);
33    INSERT INTO t1 VALUES(1,'abcdefgh');
34    INSERT INTO t1 SELECT a+1, b||b FROM t1;
35    INSERT INTO t1 SELECT a+2, b||b FROM t1;
36    INSERT INTO t1 SELECT a+4, b||b FROM t1;
37    SELECT count(*), max(length(b)) FROM t1;
38  }
39} {8 64}
40
41# Interleave two threads on read access.  Then make sure a third
42# thread can write the database.  In other words:
43#
44#    read-lock A
45#    read-lock B
46#    unlock A
47#    unlock B
48#    write-lock C
49#
50# At one point, the write-lock of C would fail on Linux.
51#
52do_test thread1-1.2 {
53  thread_create A test.db
54  thread_create B test.db
55  thread_create C test.db
56  thread_compile A {SELECT a FROM t1}
57  thread_step A
58  thread_result A
59} SQLITE_ROW
60do_test thread1-1.3 {
61  thread_argc A
62} 1
63do_test thread1-1.4 {
64  thread_argv A 0
65} 1
66do_test thread1-1.5 {
67  thread_compile B {SELECT b FROM t1}
68  thread_step B
69  thread_result B
70} SQLITE_ROW
71do_test thread1-1.6 {
72  thread_argc B
73} 1
74do_test thread1-1.7 {
75  thread_argv B 0
76} abcdefgh
77do_test thread1-1.8 {
78  thread_finalize A
79  thread_result A
80} SQLITE_OK
81do_test thread1-1.9 {
82  thread_finalize B
83  thread_result B
84} SQLITE_OK
85do_test thread1-1.10 {
86  thread_compile C {CREATE TABLE t2(x,y)}
87  thread_step C
88  thread_result C
89} SQLITE_DONE
90do_test thread1-1.11 {
91  thread_finalize C
92  thread_result C
93} SQLITE_OK
94do_test thread1-1.12 {
95  catchsql {SELECT name FROM sqlite_master}
96  execsql {SELECT name FROM sqlite_master}
97} {t1 t2}
98
99
100# Under this scenario:
101#
102#    read-lock A
103#    read-lock B
104#    unlock A
105#    write-lock C
106#
107# Make sure the write-lock fails with SQLITE_BUSY
108#
109do_test thread1-2.1 {
110  thread_halt *
111  thread_create A test.db
112  thread_compile A {SELECT a FROM t1}
113  thread_step A
114  thread_result A
115} SQLITE_ROW
116do_test thread1-2.2 {
117  thread_create B test.db
118  thread_compile B {SELECT b FROM t1}
119  thread_step B
120  thread_result B
121} SQLITE_ROW
122do_test thread1-2.3 {
123  thread_create C test.db
124  thread_compile C {INSERT INTO t2 VALUES(98,99)}
125  thread_step C
126  thread_result C
127} SQLITE_BUSY
128do_test thread1-2.4 {
129  execsql {SELECT * FROM t2}
130} {}
131do_test thread1-2.5 {
132  thread_finalize A
133  thread_result A
134} SQLITE_OK
135do_test thread1-2.6 {
136  thread_step C
137  thread_result C
138} SQLITE_BUSY
139do_test thread1-2.7 {
140  execsql {SELECT * FROM t2}
141} {}
142do_test thread1-2.8 {
143  thread_finalize B
144  thread_result B
145} SQLITE_OK
146do_test thread1-2.9 {
147  thread_step C
148  thread_result C
149} SQLITE_DONE
150do_test thread1-2.10 {
151  execsql {SELECT * FROM t2}
152} {98 99}
153do_test thread1-2.11 {
154  thread_finalize C
155  thread_result C
156} SQLITE_OK
157
158thread_halt *
159finish_test
160