summaryrefslogtreecommitdiffstats
path: root/test/mutex1.test
blob: cb189a7a8a787573f4207557187c85fdb8b4e631 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# 2008 June 17
#
# 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.
#
#***********************************************************************
#
# $Id: mutex1.test,v 1.20 2009/04/23 14:58:40 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !mutex {
  finish_test
  return
}
if {[info exists tester_do_binarylog]} {
  finish_test
  return
}

sqlite3_reset_auto_extension
clear_mutex_counters

proc mutex_counters {varname} {
  upvar $varname var
  set var(total) 0
  foreach {name value} [read_mutex_counters] {
    set var($name) $value
    incr var(total) $value
  }
}

#-------------------------------------------------------------------------
# Tests mutex1-1.* test that sqlite3_config() returns SQLITE_MISUSE if
# is called at the wrong time. And that the first time sqlite3_initialize
# is called it obtains the 'static_main' mutex 3 times and a recursive
# mutex (sqlite3Config.pInitMutex) twice. Subsequent calls are no-ops
# that do not require any mutexes.
#
do_test mutex1-1.0 {
  install_mutex_counters 1
} {SQLITE_MISUSE}

do_test mutex1-1.1 {
  db close
  install_mutex_counters 1
} {SQLITE_MISUSE}

do_test mutex1-1.2 {
  sqlite3_shutdown
  install_mutex_counters 1
} {SQLITE_OK}

do_test mutex1-1.3 {
  install_mutex_counters 0
} {SQLITE_OK}

do_test mutex1-1.4 {
  install_mutex_counters 1
} {SQLITE_OK}

do_test mutex1-1.5 {
  mutex_counters counters
  set counters(total)
} {0}

do_test mutex1-1.6 {
  sqlite3_initialize
} {SQLITE_OK}

do_test mutex1-1.7 {
  mutex_counters counters
  # list $counters(total) $counters(static_main)
  expr {$counters(total)>0}
} {1}

do_test mutex1-1.8 {
  clear_mutex_counters
  sqlite3_initialize
} {SQLITE_OK}

do_test mutex1-1.9 {
  mutex_counters counters
  list $counters(total) $counters(static_main)
} {0 0}

#-------------------------------------------------------------------------
# Tests mutex1-2.* test the three thread-safety related modes that
# can be selected using sqlite3_config:
#
#   * Serialized mode,
#   * Multi-threaded mode,
#   * Single-threaded mode.
#
ifcapable threadsafe1&&shared_cache {
  set enable_shared_cache [sqlite3_enable_shared_cache 1]
  foreach {mode mutexes} {
    singlethread {}
    multithread  {
      fast static_app1 static_app2 static_app3
      static_lru static_main static_mem static_open
      static_prng static_pmem static_vfs1 static_vfs2
      static_vfs3
    }
    serialized  {
      fast recursive static_app1 static_app2
      static_app3 static_lru static_main static_mem
      static_open static_prng static_pmem static_vfs1
      static_vfs2 static_vfs3
    }
  } {

    # For journal_mode=memory, the static_prng mutex is not required. This
    # is because the header of an in-memory journal does not contain
    # any random bytes, and so no call to sqlite3_randomness() is made.
    if {[permutation]=="inmemory_journal"} {
      set idx [lsearch $mutexes static_prng]
      if {$idx>=0} { set mutexes [lreplace $mutexes $idx $idx] }
    }

    do_test mutex1.2.$mode.1 {
      catch {db close}
      sqlite3_shutdown
      sqlite3_config_memstatus 1
      sqlite3_config $mode
    } SQLITE_OK

    do_test mutex1.2.$mode.2 {
      sqlite3_initialize
      clear_mutex_counters
      sqlite3 db test.db -nomutex 0 -fullmutex 0
      catchsql { CREATE TABLE abc(a, b, c) }
      db eval {
        INSERT INTO abc VALUES(1, 2, 3);
      }
    } {}
    ifcapable !memorymanage {
      regsub { static_lru} $mutexes {} mutexes
    }
    if {$mode ne "singlethread"} {
      do_test mutex1.2.$mode.3 {
        #
        # NOTE: Make sure all the app and vfs mutexes get used.
        #
        enter_static_mutex static_app1
        leave_static_mutex static_app1
        enter_static_mutex static_app2
        leave_static_mutex static_app2
        enter_static_mutex static_app3
        leave_static_mutex static_app3
        enter_static_mutex static_vfs1
        leave_static_mutex static_vfs1
        enter_static_mutex static_vfs2
        leave_static_mutex static_vfs2
        enter_static_mutex static_vfs3
        leave_static_mutex static_vfs3
      } {}
    }
    do_test mutex1.2.$mode.4 {
      mutex_counters counters

      set res [list]
      foreach {key value} [array get counters] {
        if {$key ne "total" && $value > 0} {
          lappend res $key
        }
      }
      lsort $res
    } [lsort $mutexes]
  }
  sqlite3_enable_shared_cache $enable_shared_cache

  # Open and use a connection in "nomutex" mode. Test that no recursive
  # mutexes are obtained.
  do_test mutex1.3.1 {
    catch {db close}
    clear_mutex_counters
    sqlite3 db test.db -nomutex 1
    execsql { SELECT * FROM abc }
  } {1 2 3 1 2 3 1 2 3}
  do_test mutex1.3.2 {
    mutex_counters counters
    set counters(recursive)
  } {0}
}

# Test the sqlite3_db_mutex() function.
#
do_test mutex1.4.1 {
  catch {db close}
  sqlite3 db test.db
  enter_db_mutex db
  db eval {SELECT 1, 2, 3}
} {1 2 3}
do_test mutex1.4.2 {
  leave_db_mutex db
  db eval {SELECT 1, 2, 3}
} {1 2 3}
do_test mutex1.4.3 {
  catch {db close}
  sqlite3 db test.db -nomutex 1
  enter_db_mutex db
  db eval {SELECT 1, 2, 3}
} {1 2 3}
do_test mutex1.4.4 {
  leave_db_mutex db
  db eval {SELECT 1, 2, 3}
} {1 2 3}

do_test mutex1-X {
  catch {db close}
  sqlite3_shutdown
  clear_mutex_counters
  install_mutex_counters 0
  sqlite3_initialize
} {SQLITE_OK}

autoinstall_test_functions
finish_test