xref: /sqlite-3.40.0/test/thread001.test (revision 570f7e25)
1# 2007 September 7
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11#
12# $Id: thread001.test,v 1.2 2007/09/07 18:40:38 danielk1977 Exp $
13
14set testdir [file dirname $argv0]
15source $testdir/tester.tcl
16
17if {[info commands sqlthread] eq ""} {
18  puts -nonewline "Skipping thread-safety tests - "
19  puts            " not running a threadsafe sqlite/tcl build"
20  puts -nonewline "Both SQLITE_THREADSAFE and TCL_THREADS must be defined when"
21  puts            " building testfixture"
22  finish_test
23  return
24}
25
26# Set up a database and a schema. The database contains a single
27# table with two columns. The first column ("a") is an INTEGER PRIMARY
28# KEY. The second contains the md5sum of all rows in the table with
29# a smaller value stored in column "a".
30#
31do_test thread001.1 {
32  execsql {
33    CREATE TABLE ab(a INTEGER PRIMARY KEY, b);
34    CREATE INDEX ab_i ON ab(b);
35    INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab;
36    SELECT count(*) FROM ab;
37  }
38} {1}
39do_test thread001.2 {
40  execsql {
41    SELECT
42      (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
43      (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
44  }
45} {1}
46do_test thread001.3 {
47  execsql { PRAGMA integrity_check }
48} {ok}
49
50set thread_program [format {
51  set ::DB %s
52
53  # Execute the supplied SQL using database handle $::DB.
54  #
55  proc execsql {sql} {
56    set res [list]
57    set ::STMT [sqlite3_prepare $::DB $sql -1 dummy_tail]
58    while {[sqlite3_step $::STMT] eq "SQLITE_ROW"} {
59      for {set i 0} {$i < [sqlite3_column_count $::STMT]} {incr i} {
60        lappend res [sqlite3_column_text $::STMT 0]
61      }
62    }
63    set rc [sqlite3_finalize $::STMT]
64    if {$rc ne "SQLITE_OK"} {
65      error [sqlite3_errmsg $::DB]
66    }
67    set res
68  }
69
70  proc do_test {name script result} {
71    set res [eval $script]
72    if {$res ne $result} {
73      error "$name failed: expected \"$result\" got \"$res\""
74    }
75  }
76
77  for {set i 0} {$i < 100} {incr i} {
78    # Test that the invariant is true.
79    do_test t1 {
80      execsql {
81        SELECT
82          (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
83          (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
84      }
85    } {1}
86
87    # Add another row to the database.
88    execsql { INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab }
89  }
90
91  list OK
92} [sqlite3_connection_pointer db]]
93
94# Kick off 10 threads:
95#
96array unset finished
97for {set i 0} {$i < 10} {incr i} {
98  sqlthread spawn finished($i) $thread_program
99}
100
101for {set i 0} {$i < 10} {incr i} {
102  if {![info exists finished($i)]} {
103    vwait finished($i)
104  }
105  do_test thread001.4.$i {
106    set ::finished($i)
107  } OK
108}
109
110do_test thread001.5 {
111  execsql { SELECT count(*) FROM ab; }
112} {1001}
113do_test thread001.6 {
114  execsql {
115    SELECT
116      (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
117      (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
118  }
119} {1}
120do_test thread001.7 {
121  execsql { PRAGMA integrity_check }
122} {ok}
123
124# Give the event-handlers a chance to close any open parent-child pipes.
125# Otherwise, the test is reported as leaking memory (it has not - it's
126# just that the memory is freed asynchronously).
127#
128after 250 {set abit 0}
129vwait abit
130
131finish_test
132
133