Home | History | Annotate | Download | only in test
      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.10 2009/03/26 14:48:07 danielk1977 Exp $
     13 
     14 set testdir [file dirname $argv0]
     15 
     16 source $testdir/tester.tcl
     17 if {[run_thread_tests]==0} { finish_test ; return }
     18 
     19 set ::enable_shared_cache [sqlite3_enable_shared_cache]
     20 
     21 set ::NTHREAD 10
     22 
     23 # Run this test three times: 
     24 # 
     25 #    1) All threads use the same database handle.
     26 #    2) All threads use their own database handles.
     27 #    3) All threads use their own database handles, shared-cache is enabled.
     28 #
     29 #
     30 #
     31 foreach {tn same_db shared_cache} [list \
     32          1  1       0                   \
     33          2  0       0                   \
     34          3  0       1                   \
     35 ] {
     36   # Empty the database.
     37   #
     38   catchsql { DROP TABLE ab; }
     39 
     40   do_test thread001.$tn.0 {
     41     db close
     42     sqlite3_enable_shared_cache $shared_cache
     43     sqlite3_enable_shared_cache $shared_cache
     44   } $shared_cache
     45   sqlite3 db test.db -fullmutex 1
     46 
     47   set dbconfig ""
     48   if {$same_db} {
     49     set dbconfig [list set ::DB [sqlite3_connection_pointer db]]
     50   }
     51 
     52   # Set up a database and a schema. The database contains a single
     53   # table with two columns. The first column ("a") is an INTEGER PRIMARY 
     54   # KEY. The second contains the md5sum of all rows in the table with
     55   # a smaller value stored in column "a".
     56   #
     57   do_test thread001.$tn.1 {
     58     execsql {
     59       CREATE TABLE ab(a INTEGER PRIMARY KEY, b);
     60       CREATE INDEX ab_i ON ab(b);
     61       INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab;
     62       SELECT count(*) FROM ab;
     63     }
     64   } {1}
     65   do_test thread001.$tn.2 {
     66     execsql {
     67       SELECT 
     68         (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
     69         (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
     70     }
     71   } {1}
     72   do_test thread001.$tn.3 {
     73     execsql { PRAGMA integrity_check }
     74   } {ok}
     75 
     76   set thread_program {
     77     #sqlthread parent {puts STARTING..}
     78     set needToClose 0
     79     if {![info exists ::DB]} {
     80       set ::DB [sqlthread open test.db]
     81       #sqlthread parent "puts \"OPEN $::DB\""
     82       set needToClose 1
     83     }
     84   
     85     for {set i 0} {$i < 100} {incr i} {
     86       # Test that the invariant is true.
     87       do_test t1 {
     88         execsql {
     89           SELECT 
     90             (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
     91             (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
     92         }
     93       } {1}
     94   
     95       # Add another row to the database.
     96       execsql { INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab }
     97     }
     98   
     99     if {$needToClose} {
    100       #sqlthread parent "puts \"CLOSE $::DB\""
    101       sqlite3_close $::DB
    102     }
    103     #sqlthread parent "puts \"DONE\""
    104   
    105     list OK
    106   }
    107   
    108   # Kick off $::NTHREAD threads:
    109   #
    110   array unset finished
    111   for {set i 0} {$i < $::NTHREAD} {incr i} {
    112     thread_spawn finished($i) $dbconfig $thread_procs $thread_program
    113   }
    114   
    115   # Wait for all threads to finish,  then check they all returned "OK".
    116   #
    117   for {set i 0} {$i < $::NTHREAD} {incr i} {
    118     if {![info exists finished($i)]} {
    119       vwait finished($i)
    120     }
    121     do_test thread001.$tn.4.$i {
    122       set ::finished($i)
    123     } OK
    124   }
    125   
    126   # Check the database still looks Ok.
    127   #
    128   do_test thread001.$tn.5 {
    129     execsql { SELECT count(*) FROM ab; }
    130   } [expr {1 + $::NTHREAD*100}]
    131   do_test thread001.$tn.6 {
    132     execsql {
    133       SELECT 
    134         (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) ==
    135         (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab))
    136     }
    137   } {1}
    138   do_test thread001.$tn.7 {
    139     execsql { PRAGMA integrity_check }
    140   } {ok}
    141 }
    142 
    143 sqlite3_enable_shared_cache $::enable_shared_cache
    144 set sqlite_open_file_count 0
    145 finish_test
    146