]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add tests to walthread.test.
authordan <dan@noemail.net>
Thu, 29 Apr 2010 08:47:28 +0000 (08:47 +0000)
committerdan <dan@noemail.net>
Thu, 29 Apr 2010 08:47:28 +0000 (08:47 +0000)
FossilOrigin-Name: 9e891e7543ea4d7dee76deb2456af940f4cac49b

manifest
manifest.uuid
test/walthread.test

index 8d7772b612c56721a3daa0c5558fca26eaf8fc77..d16501f28fe27b17da11bc187730c8fa8d48860a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sa\stest\sto\swalthread.test\sfor\schanging\sbetween\sWAL\sand\srollback\smodes.
-D 2010-04-28T18:17:23
+C Add\stests\sto\swalthread.test.
+D 2010-04-29T08:47:28
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in d83a0ffef3dcbfb08b410a6c6dd6c009ec9167fb
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -764,7 +764,7 @@ F test/walcrash.test f022cee7eb7baa5fb898726120a6a4073dd831d1
 F test/walhook.test 287a69d662939604f2e0452dace2cec8ef634d5e
 F test/walmode.test 40119078da084e6a7403ba57485d5a86ee0e2646
 F test/walslow.test 38076d5fad49e3678027be0f8110e6a32d531dc2
-F test/walthread.test ce1d0fc9905cf8a7cf1a61dbcafcbd3434166236
+F test/walthread.test 8fdce1721bf01e88a1f83a93ce7ae2e7668bcb26
 F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
 F test/where2.test 45eacc126aabb37959a387aa83e59ce1f1f03820
 F test/where3.test aa44a9b29e8c9f3d7bb94a3bb3a95b31627d520d
@@ -808,7 +808,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 13d2d5a66e9eaa81aa6314354201ee1fbd2b3824
-R 03ea219fce1817690b6cb9bee0a76d8a
+P da229e44bd4a5d512261da05958d560808c9889f
+R f40b5481d2db02fd1a8b59b3cbe35412
 U dan
-Z e37b4277b60d879edbf1e6cb6d434b3c
+Z 9a86a68774ea80363d82258dc9f803a1
index c424e5c417c1fd2166ebd4133e11623721c7f315..cfa4e1552051f362dae5fbc1cba73498711e3c6b 100644 (file)
@@ -1 +1 @@
-da229e44bd4a5d512261da05958d560808c9889f
\ No newline at end of file
+9e891e7543ea4d7dee76deb2456af940f4cac49b
\ No newline at end of file
index 057ba2396f2ccbe58ee550fb62a0f93609741b20..353b7e42ddf6d5fafad27d45b8c6769687fb7af0 100644 (file)
@@ -21,11 +21,12 @@ if {[run_thread_tests]==0} { finish_test ; return }
 
 set sqlite_walsummary_mmap_incr 64
 
-# The number of threads to start. And the amount of time to run the test
-# for. Respectively.
+# How long, in seconds, to run each test for. If a test is set to run for
+# 0 seconds, it is omitted entirely.
 #
-set NTHREAD 10
-set SECONDS 5
+set seconds(walthread-1)  0
+set seconds(walthread-2)  0
+set seconds(walthread-3) 20
 
 # The parameter is the name of a variable in the callers context. The
 # variable may or may not exist when this command is invoked.
@@ -42,6 +43,13 @@ proc wait_for_var {varname} {
   uplevel [list set $varname]
 }
 
+# The argument is the name of a list variable in the callers context. The 
+# first element of the list is removed and returned. For example:
+#
+#   set L {a b c}
+#   set x [lshift L]
+#   assert { $x == "a" && $L == "b c" }
+#
 proc lshift {lvar} {
   upvar $lvar L
   set ret [lindex $L 0]
@@ -59,11 +67,10 @@ proc lshift {lvar} {
 #   -init      SCRIPT                 Script to run before test.
 #   -thread    NAME COUNT SCRIPT      Scripts to run in threads (or processes).
 #   -processes BOOLEAN                True to use processes instead of threads.
+#   -check     SCRIPT                 Script to run after test.
 #
 proc do_thread_test {args} {
 
-  #if {[string match walthread-2* [lindex $args 0]]==0} return
-
   set A $args
 
   set P(testname) [lshift A]
@@ -71,6 +78,10 @@ proc do_thread_test {args} {
   set P(init) ""
   set P(threads) [list]
   set P(processes) 0
+  set P(check) {
+    set ic [db eval "PRAGMA integrity_check"]
+    if {$ic != "ok"} { error $ic }
+  }
 
   unset -nocomplain ::done
 
@@ -89,6 +100,10 @@ proc do_thread_test {args} {
         set P(processes) [lshift A]
       }
 
+      -check {
+        set P(check) [lshift A]
+      }
+
       -thread {
         set name  [lshift A]
         set count [lshift A]
@@ -102,6 +117,11 @@ proc do_thread_test {args} {
     }
   }
 
+  if {$P(seconds) == 0} {
+    puts "Skipping $P(testname)"
+    return
+  }
+
   puts "Running $P(testname) for $P(seconds) seconds..."
 
   catch { db close }
@@ -117,23 +137,34 @@ proc do_thread_test {args} {
     set prg   [lindex $T 2]
 
     for {set i 1} {$i <= $count} {incr i} {
-      set program [string map [list %TEST% $prg %SECONDS% $P(seconds) %I% $i] {
+      set vars "
+        set E(pid) $i
+        set E(nthread) $count
+        set E(seconds) $P(seconds)
+      "
+      set program [string map [list %TEST% $prg %VARS% $vars] {
 
-        set tid %I%
+        %VARS%
 
         proc usleep {ms} {
           set ::usleep 0
           after $ms {set ::usleep 1}
           vwait ::usleep
         }
+
+        proc integrity_check {{db db}} {
+          set ic [$db eval {PRAGMA integrity_check}]
+          if {$ic != "ok"} {error $ic}
+        }
+
         proc busyhandler {n} { usleep 10 ; return 0 }
 
         sqlite3 db test.db
         db busy busyhandler
-        db eval { SELECT randomblob($tid*5) }
+        db eval { SELECT randomblob($E(pid)*5) }
 
         set ::finished 0
-        after [expr %SECONDS% * 1000] {set ::finished 1}
+        after [expr $E(seconds) * 1000] {set ::finished 1}
         proc tt_continue {} { update ; expr ($::finished==0) }
 
         set rc [catch { %TEST% } msg]
@@ -166,10 +197,28 @@ proc do_thread_test {args} {
     append report "   $name $reslist"
   }
   puts $report
+
+  sqlite3 db test.db
+  set res ""
+  if {[catch $P(check) msg]} { set res $msg }
+  do_test $P(testname).check [list set {} $res] ""
 }
 
+# A wrapper around [do_thread_test] which runs the specified test twice.
+# Once using processes, once using threads. This command takes the same
+# arguments as [do_thread_test], except specifying the -processes switch
+# is illegal.
+#
+proc do_thread_test2 {args} {
+  set name [lindex $args 0]
+  if {[lsearch $args -processes]>=0} { error "bad option: -processes"}
+  uplevel [lreplace $args 0 0 do_thread_test "$name-threads" -processes 0]
+  uplevel [lreplace $args 0 0 do_thread_test "$name-processes" -processes 1]
+}
+
+
 #--------------------------------------------------------------------------
-# Start NTHREAD threads. Each thread performs both read and write 
+# Start 10 threads. Each thread performs both read and write 
 # transactions. Each read transaction consists of:
 #
 #   1) Reading the md5sum of all but the last table row,
@@ -192,124 +241,187 @@ proc do_thread_test {args} {
 #   1) Execute "PRAGMA checkpoint"
 #   2) Sleep for 500 ms.
 #
-
-foreach {mode name} {
-      0 walthread-1-threads 
-      1 walthread-1-processes
-} {
-  do_thread_test $name -processes $mode -seconds $SECONDS -init {
-    execsql {
-      PRAGMA journal_mode = WAL;
-      CREATE TABLE t1(x PRIMARY KEY);
-      PRAGMA lock_status;
-      INSERT INTO t1 VALUES(randomblob(100));
-      INSERT INTO t1 VALUES(randomblob(100));
-      INSERT INTO t1 SELECT md5sum(x) FROM t1;
-    }
-  } -thread main $NTHREAD {
-  
-    proc read_transaction {} {
-      set results [db eval {
-        BEGIN;
-          PRAGMA integrity_check;
-          SELECT md5sum(x) FROM t1 WHERE rowid != (SELECT max(rowid) FROM t1);
-          SELECT x FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1);
-          SELECT md5sum(x) FROM t1 WHERE rowid != (SELECT max(rowid) FROM t1);
-        COMMIT;
-      }]
-  
-      if {[llength $results]!=4
-       || [lindex $results 0] != "ok"
-       || [lindex $results 1] != [lindex $results 2]
-       || [lindex $results 2] != [lindex $results 3]
-      } {
-        error "Failed read transaction: $results"
-      }
-    }
-  
-    proc write_transaction {} {
-      db eval {
-        BEGIN;
-          INSERT INTO t1 VALUES(randomblob(100));
-          INSERT INTO t1 VALUES(randomblob(100));
-          INSERT INTO t1 SELECT md5sum(x) FROM t1;
-        COMMIT;
-      }
-    }
-  
-    set nRun 0
-    while {[tt_continue]} {
-      read_transaction
-      write_transaction 
-      incr nRun
+do_thread_test2 walthread-1 -seconds $seconds(walthread-1) -init {
+  execsql {
+    PRAGMA journal_mode = WAL;
+    CREATE TABLE t1(x PRIMARY KEY);
+    PRAGMA lock_status;
+    INSERT INTO t1 VALUES(randomblob(100));
+    INSERT INTO t1 VALUES(randomblob(100));
+    INSERT INTO t1 SELECT md5sum(x) FROM t1;
+  }
+} -thread main 10 {
+
+  proc read_transaction {} {
+    set results [db eval {
+      BEGIN;
+        PRAGMA integrity_check;
+        SELECT md5sum(x) FROM t1 WHERE rowid != (SELECT max(rowid) FROM t1);
+        SELECT x FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1);
+        SELECT md5sum(x) FROM t1 WHERE rowid != (SELECT max(rowid) FROM t1);
+      COMMIT;
+    }]
+
+    if {[llength $results]!=4
+     || [lindex $results 0] != "ok"
+     || [lindex $results 1] != [lindex $results 2]
+     || [lindex $results 2] != [lindex $results 3]
+    } {
+      error "Failed read transaction: $results"
     }
-    set nRun
-  
-  } -thread ckpt 1 {
-    set nRun 0
-    while {[tt_continue]} {
-      db eval "PRAGMA checkpoint"
-      usleep 500
-      incr nRun
+  }
+
+  proc write_transaction {} {
+    db eval {
+      BEGIN;
+        INSERT INTO t1 VALUES(randomblob(100));
+        INSERT INTO t1 VALUES(randomblob(100));
+        INSERT INTO t1 SELECT md5sum(x) FROM t1;
+      COMMIT;
     }
-    set nRun
   }
+
+  set nRun 0
+  while {[tt_continue]} {
+    read_transaction
+    write_transaction 
+    incr nRun
+  }
+  set nRun
+
+} -thread ckpt 1 {
+  set nRun 0
+  while {[tt_continue]} {
+    db eval "PRAGMA checkpoint"
+    usleep 500
+    incr nRun
+  }
+  set nRun
 }
 
 #--------------------------------------------------------------------------
+# This test has clients run the following procedure as fast as possible
+# in a loop:
+#
+#   1. Open a database handle.
+#   2. Execute a read-only transaction on the db.
+#   3. Do "PRAGMA journal_mode = XXX", where XXX is one of WAL or DELETE.
+#      Ignore any SQLITE_BUSY error.
+#   4. Execute a write transaction to insert a row into the db.
+#   5. Run "PRAGMA integrity_check"
 #
-foreach {mode name} {
-      0 walthread-2-threads 
-      1 walthread-2-processes
-} {
-  do_thread_test $name -processes $mode -seconds $SECONDS -init {
-    execsql { CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE) }
-  } -thread RB 2 {
+# At present, there are 4 clients in total. 2 do "journal_mode = WAL", and
+# two do "journal_mode = DELETE".
+#
+# Each client returns a string of the form "W w, R r", where W is the 
+# number of write-transactions performed using a WAL journal, and D is
+# the number of write-transactions performed using a rollback journal.
+# For example, "192 w, 185 r".
+#
+do_thread_test2 walthread-2 -seconds $seconds(walthread-2) -init {
+  execsql { CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE) }
+} -thread RB 2 {
+
+  db close
+  set nRun 0
+  set nDel 0
+  while {[tt_continue]} {
+    sqlite3 db test.db
+    db busy busyhandler
+    db eval { SELECT * FROM sqlite_master }
+    catch { db eval { PRAGMA journal_mode = DELETE } }
+    db eval {
+      BEGIN;
+      INSERT INTO t1 VALUES(NULL, randomblob(100+$E(pid)));
+    }
+    incr nRun 1
+    incr nDel [file exists test.db-journal]
+    if {[file exists test.db-journal] + [file exists test.db-wal] != 1} {
+      error "File-system looks bad..."
+    }
+    db eval COMMIT
 
+    integrity_check
     db close
-    set nRun 0
-    set nDel 0
-    while {[tt_continue]} {
-      sqlite3 db test.db
-      db busy busyhandler
-      db eval { SELECT * FROM sqlite_master }
-      catch { db eval { PRAGMA journal_mode = DELETE } }
-      db eval {
-        BEGIN;
-        INSERT INTO t1 VALUES(NULL, randomblob(100+$tid));
-      }
-      incr nRun 1
-      incr nDel [file exists test.db-journal]
-      db eval COMMIT
+  }
+  list $nRun $nDel
+  set {} "[expr $nRun-$nDel] w, $nDel r"
 
-      set ic [db eval {PRAGMA integrity_check}]
-      if {$ic != "ok"} { error $ic }
-      db close
+} -thread WAL 2 {
+  db close
+  set nRun 0
+  set nDel 0
+  while {[tt_continue]} {
+    sqlite3 db test.db
+    db busy busyhandler
+    db eval { SELECT * FROM sqlite_master }
+    catch { db eval { PRAGMA journal_mode = WAL } }
+    db eval {
+      BEGIN;
+      INSERT INTO t1 VALUES(NULL, randomblob(110+$E(pid)));
+    }
+    incr nRun 1
+    incr nDel [file exists test.db-journal]
+    if {[file exists test.db-journal] + [file exists test.db-wal] != 1} {
+      error "File-system looks bad..."
     }
-    list $nRun $nDel
+    db eval COMMIT
 
-  } -thread WAL 2 {
+    integrity_check
     db close
-    set nRun 0
-    set nWal 0
-    while {[tt_continue]} {
-      sqlite3 db test.db
-      db busy busyhandler
-      db eval { SELECT * FROM sqlite_master }
-      catch { db eval { PRAGMA journal_mode = WAL } }
-      db eval {
-        BEGIN;
-        INSERT INTO t1 VALUES(NULL, randomblob(110+$tid));
-      }
-      incr nRun 1
-      incr nWal [file exists test.db-wal]
-      db eval COMMIT
+  }
+  set {} "[expr $nRun-$nDel] w, $nDel r"
+}
+
+do_thread_test2 walthread-3 -seconds $seconds(walthread-3) -init {
+  execsql {
+    PRAGMA journal_mode = WAL;
+    CREATE TABLE t1(cnt PRIMARY KEY, sum1, sum2);
+    CREATE INDEX i1 ON t1(sum1);
+    CREATE INDEX i2 ON t1(sum2);
+    INSERT INTO t1 VALUES(0, 0, 0);
+  }
+} -thread t 10 {
+
+  set nextwrite $E(pid)
+
+  proc wal_hook {zDb nEntry} {
+    if {$nEntry>10} { return 1 }
+    return 0
+  }
+  db wal_hook wal_hook
+
+  while {[tt_continue]} {
+    set max 0
+    while { $max != ($nextwrite-1) && [tt_continue] } {
+      set max [db eval { SELECT max(cnt) FROM t1 }]
+    }
+
+    if {[tt_continue]} {
+      set sum1 [db eval { SELECT sum(cnt) FROM t1 }]
+      set sum2 [db eval { SELECT sum(sum1) FROM t1 }]
+      db eval { INSERT INTO t1 VALUES($nextwrite, $sum1, $sum2) }
+      incr nextwrite $E(nthread)
+      integrity_check
+    }
+  }
 
-      set ic [db eval {PRAGMA integrity_check}]
-      if {$ic != "ok"} { error $ic }
-      db close
+  set {} ok
+} -check {
+  puts "  Final db contains [db eval {SELECT count(*) FROM t1}] rows"
+  puts "  Final integrity-check says: [db eval {PRAGMA integrity_check}]"
+
+  # Check that the contents of the database are Ok.
+  set c 0
+  set s1 0
+  set s2 0
+  db eval { SELECT cnt, sum1, sum2 FROM t1 ORDER BY cnt } {
+    if {$c != $cnt || $s1 != $sum1 || $s2 != $sum2} {
+      error "database content is invalid"
     }
-    list $nRun $nWal
+    incr s2 $s1
+    incr s1 $c
+    incr c 1
   }
 }