xref: /sqlite-3.40.0/test/thread001.test (revision 44918fa0)
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.1 2007/09/07 11:29:25 danielk1977 Exp $
13
14set testdir [file dirname $argv0]
15source $testdir/tester.tcl
16
17if {[info commands sqlthread] eq ""} {
18  puts "Skipping thread-safety tests - not running a threadsafe unix build"
19  finish_test
20  return
21}
22
23# Set up a database and a schema. The database contains a single
24# table with two columns. The first column ("a") is an INTEGER PRIMARY
25# KEY. The second contains the md5sum of all rows in the table with
26# a smaller value stored in column "a".
27#
28do_test thread001.1 {
29  execsql {
30    CREATE TABLE ab(a INTEGER PRIMARY KEY, b);
31    CREATE INDEX ab_i ON ab(b);
32    INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab;
33    SELECT count(*) FROM ab;
34  }
35} {1}
36do_test thread001.2 {
37  execsql {
38    SELECT
39      (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
40      (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
41  }
42} {1}
43do_test thread001.3 {
44  execsql { PRAGMA integrity_check }
45} {ok}
46
47set thread_program [format {
48  set ::DB %s
49
50  # Execute the supplied SQL using database handle $::DB.
51  #
52  proc execsql {sql} {
53    set res [list]
54    set ::STMT [sqlite3_prepare $::DB $sql -1 dummy_tail]
55    while {[sqlite3_step $::STMT] eq "SQLITE_ROW"} {
56      for {set i 0} {$i < [sqlite3_column_count $::STMT]} {incr i} {
57        lappend res [sqlite3_column_text $::STMT 0]
58      }
59    }
60    set rc [sqlite3_finalize $::STMT]
61    if {$rc ne "SQLITE_OK"} {
62      error [sqlite3_errmsg $::DB]
63    }
64    set res
65  }
66
67  for {set i 0} {$i < 100} {incr i} {
68    # Test that the invariant is true.
69    set val [execsql {
70      SELECT
71        (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
72        (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
73    }]
74    if {$val ne "1"} {error "Invariant test failed"}
75
76    # Add another row to the database.
77    execsql { INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab }
78  }
79
80  list OK
81} [sqlite3_connection_pointer db]]
82
83# Kick off 10 threads:
84#
85array unset finished
86for {set i 0} {$i < 10} {incr i} {
87  sqlthread spawn finished($i) $thread_program
88}
89
90for {set i 0} {$i < 10} {incr i} {
91  if {![info exists finished($i)]} {
92    vwait finished($i)
93  }
94  do_test thread001.4.$i {
95    set ::finished($i)
96  } OK
97}
98
99do_test thread001.5 {
100  execsql { SELECT count(*) FROM ab; }
101} {1001}
102do_test thread001.6 {
103  execsql {
104    SELECT
105      (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
106      (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
107  }
108} {1}
109do_test thread001.7 {
110  execsql { PRAGMA integrity_check }
111} {ok}
112
113# Give the event-handlers a chance to close any open parent-child pipes.
114# Otherwise, the test is reported as leaking memory (it has not - it's
115# just that the memory is freed asynchronously).
116#
117after 250 {set abit 0}
118vwait abit
119
120finish_test
121
122