gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/thread003.test (about)

     1  # 2007 September 10
     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  #   This file contains tests that attempt to break the pcache module
    13  #   by bombarding it with simultaneous requests from multiple threads.
    14  #     
    15  # $Id: thread003.test,v 1.8 2009/03/26 14:48:07 danielk1977 Exp $
    16  
    17  set testdir [file dirname $argv0]
    18  
    19  source $testdir/tester.tcl
    20  if {[run_thread_tests]==0} { finish_test ; return }
    21  
    22  # Set up a couple of different databases full of pseudo-randomly 
    23  # generated data.
    24  #
    25  do_test thread003.1.1 {
    26    execsql {
    27      BEGIN;
    28      CREATE TABLE t1(a, b, c);
    29    }
    30    for {set ii 0} {$ii < 5000} {incr ii} {
    31      execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))}
    32    }
    33    execsql { 
    34      CREATE INDEX i1 ON t1(a, b); 
    35      COMMIT;
    36    }
    37  } {}
    38  do_test thread003.1.2 {
    39    expr {([file size test.db] / 1024) > 2000}
    40  } {1}
    41  do_test thread003.1.3 {
    42    db close
    43    forcedelete test2.db
    44    sqlite3 db test2.db
    45  } {}
    46  do_test thread003.1.4 {
    47    execsql {
    48      BEGIN;
    49      CREATE TABLE t1(a, b, c);
    50    }
    51    for {set ii 0} {$ii < 5000} {incr ii} {
    52      execsql {INSERT INTO t1 VALUES($ii, randomblob(200), randomblob(200))}
    53    }
    54    execsql { 
    55      CREATE INDEX i1 ON t1(a, b); 
    56      COMMIT;
    57    }
    58  } {}
    59  do_test thread003.1.5 {
    60    expr {([file size test.db] / 1024) > 2000}
    61  } {1}
    62  do_test thread003.1.6 {
    63    db close
    64  } {}
    65  
    66  
    67  # This test opens a connection on each of the large (>2MB) database files
    68  # created by the previous block. The connections do not share a cache.
    69  # Both "cache_size" parameters are set to 15, so there is a maximum of
    70  # 30 pages available globally.
    71  #
    72  # Then, in separate threads, the databases are randomly queried over and
    73  # over again. This will force the connections to recycle clean pages from
    74  # each other. If there is a thread-safety problem, a segfault or assertion
    75  # failure may eventually occur.
    76  #
    77  set nSecond 30
    78  puts "Starting thread003.2 (should run for ~$nSecond seconds)"
    79  do_test thread003.2 {
    80    foreach zFile {test.db test2.db} {
    81      set SCRIPT [format {
    82        set iEnd [expr {[clock_seconds] + %d}]
    83        set ::DB [sqlthread open %s xyzzy]
    84    
    85        # Set the cache size to 15 pages per cache. 30 available globally.
    86        execsql { PRAGMA cache_size = 15 }
    87    
    88        while {[clock_seconds] < $iEnd} {
    89          set iQuery [expr {int(rand()*5000)}]
    90          execsql " SELECT * FROM t1 WHERE a = $iQuery "
    91        }
    92    
    93        sqlite3_close $::DB
    94        expr 1
    95      } $nSecond $zFile]
    96    
    97      unset -nocomplain finished($zFile)
    98      thread_spawn finished($zFile) $thread_procs $SCRIPT
    99    }
   100    foreach zFile {test.db test2.db} {
   101      if {![info exists finished($zFile)]} {
   102        vwait finished($zFile)
   103      }
   104    }
   105    expr 0
   106  } {0}
   107  
   108  # This test is the same as the test above, except that each thread also
   109  # writes to the database. This causes pages to be moved back and forth 
   110  # between the caches internal dirty and clean lists, which is another
   111  # opportunity for a thread-related bug to present itself.
   112  #
   113  set nSecond 30
   114  puts "Starting thread003.3 (should run for ~$nSecond seconds)"
   115  do_test thread003.3 {
   116    foreach zFile {test.db test2.db} {
   117      set SCRIPT [format {
   118        set iStart [clock_seconds]
   119        set iEnd [expr {[clock_seconds] + %d}]
   120        set ::DB [sqlthread open %s xyzzy]
   121    
   122        # Set the cache size to 15 pages per cache. 30 available globally.
   123        execsql { PRAGMA cache_size = 15 }
   124    
   125        while {[clock_seconds] < $iEnd} {
   126          set iQuery [expr {int(rand()*5000)}]
   127          execsql "SELECT * FROM t1 WHERE a = $iQuery"
   128          execsql "UPDATE t1 SET b = randomblob(200) 
   129                   WHERE a < $iQuery AND a > $iQuery + 20
   130          "
   131        }
   132    
   133        sqlite3_close $::DB
   134        expr 1
   135      } $nSecond $zFile]
   136    
   137      unset -nocomplain finished($zFile)
   138      thread_spawn finished($zFile) $thread_procs $SCRIPT
   139    }
   140    foreach zFile {test.db test2.db} {
   141      if {![info exists finished($zFile)]} {
   142        vwait finished($zFile)
   143      }
   144    }
   145    expr 0
   146  } {0}
   147  
   148  # In this test case, one thread is continually querying the database.
   149  # The other thread does not have a database connection, but calls
   150  # sqlite3_release_memory() over and over again.
   151  #
   152  set nSecond 30
   153  puts "Starting thread003.4 (should run for ~$nSecond seconds)"
   154  unset -nocomplain finished(1)
   155  unset -nocomplain finished(2)
   156  do_test thread003.4 {
   157    thread_spawn finished(1) $thread_procs [format {
   158      set iEnd [expr {[clock_seconds] + %d}]
   159      set ::DB [sqlthread open test.db xyzzy]
   160  
   161      # Set the cache size to 15 pages per cache. 30 available globally.
   162      execsql { PRAGMA cache_size = 15 }
   163  
   164      while {[clock_seconds] < $iEnd} {
   165        set iQuery [expr {int(rand()*5000)}]
   166        execsql "SELECT * FROM t1 WHERE a = $iQuery"
   167      }
   168  
   169      sqlite3_close $::DB
   170      expr 1
   171    } $nSecond] 
   172    thread_spawn finished(2) [format {
   173      set iEnd [expr {[clock_seconds] + %d}]
   174  
   175      while {[clock_seconds] < $iEnd} {
   176        sqlite3_release_memory 1000
   177      }
   178    } $nSecond]
   179    
   180    foreach ii {1 2} {
   181      if {![info exists finished($ii)]} {
   182        vwait finished($ii)
   183      }
   184    }
   185    expr 0
   186  } {0}
   187  
   188  set sqlite_open_file_count 0
   189  finish_test