System.Data.SQLite
Artifact Content
Not logged in

Artifact 70ae7e37950b6231e46b923a7028460bd0bf3090:


###############################################################################
#
# stress.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

###############################################################################

runTest {test stress-1.1 {multithreaded stress testing} -setup {
  proc failThisTest { error } {
    set level [expr {[info level] - 1}]

    puts stdout ""
    puts stdout [appendArgs [info level $level] ": " $error]
    puts stdout ""

    exit Failure; # halt all testing now.
  }

  #############################################################################

  set count(0) 1
  set count(1) 10

  if {[info exists argv] && [llength $argv] > 0} then {
    parse options [list \
        [list null MustHaveIntegerValue -1 -1 -count0 $count(0)] \
        [list null MustHaveIntegerValue -1 -1 -count1 $count(1)]] $argv

    set count(0) $options(-count0,value)
    set count(1) $options(-count1,value)
  }

  #############################################################################

  tputs $test_channel [appendArgs \
      "---- workloads will repeat " $count(0) " time(s)...\n"]

  tputs $test_channel [appendArgs \
      "---- workloads will have " $count(1) " iteration(s)...\n"]

  #############################################################################

  setupDb [set fileName(1) :memory:] "" "" "" "" "" false srcDb
  setupDb [set fileName(2) [file join [getDatabaseDirectory] stress.db]]

  #############################################################################

  set workload(1) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #1, CREATE TABLE statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 2} {$index <= $count} {incr index} {
        sql execute $db [appendArgs \
            "CREATE TABLE IF NOT EXISTS t" $index "(x PRIMARY KEY, y, z);"]
        puts -nonewline stdout 1; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(2) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #2, DROP TABLE statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 2} {$index <= $count} {incr index} {
        sql execute $db [appendArgs \
            "DROP TABLE IF EXISTS t" $index \;]
        puts -nonewline stdout 2; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(3) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #3, "small" SELECT statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute -execute reader $db [appendArgs \
            "SELECT x, y FROM " $table " WHERE z = 'small';"]
        puts -nonewline stdout 3; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(4) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #4, "big" SELECT statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute -execute reader $db [appendArgs \
            "SELECT x, y FROM " $table " WHERE z = 'big';"]
        puts -nonewline stdout 4; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(5) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #5, "small" INSERT statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute $db [appendArgs \
            "INSERT INTO " $table "(x, y, z) VALUES('" \
            [format %lX [expr {random()}]] "', '" \
            [base64 encode -- [expr {randstr(10000)}]] \
            "', 'small');"]
        puts -nonewline stdout 5; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(6) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #6, "big" INSERT statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute $db [appendArgs \
            "INSERT INTO " $table "(x, y, z) VALUES('" \
            [format %lX [expr {random()}]] \
            "', RANDOMBLOB(10000000), 'big');"]
        puts -nonewline stdout 6; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(7) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #7, "small" UPDATE statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute $db [appendArgs "UPDATE " $table \
            " SET y = '" [base64 encode -- [expr {randstr(10000)}]] \
            "' WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
        puts -nonewline stdout 7; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(8) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #8, "big" UPDATE statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute $db [appendArgs "UPDATE " $table \
            " SET y = RANDOMBLOB(10000000) WHERE x LIKE '" \
            [format %X $index] "%' AND z = 'big';"]
        puts -nonewline stdout 8; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(9) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #9, "small" DELETE statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute $db [appendArgs "DELETE FROM " $table \
            " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
        puts -nonewline stdout 9; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(10) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #10, "big" DELETE statements.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      for {set index 1} {$index <= $count} {incr index} {
        sql execute $db [appendArgs "DELETE FROM " $table \
            " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"]
        puts -nonewline stdout A; after [expr {int(rand() * 1000)}]
      }
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(11) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #11, VACUUM statement.
    #
    setupDb $fileName "" "" "" "" "" false
    if {[catch {
      sql execute $db "VACUUM;"
      puts -nonewline stdout B; after [expr {int(rand() * 1000)}]
    } error]} then {
      if {[regexp -- {\sno such table: t1\s} $error]} then {
        puts -nonewline stdout *
      } else {
        failThisTest $error
      }
    }
    cleanupDb $fileName db false false
  }]

  #############################################################################

  set workload(12) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #12, backup to in-memory database.
    #
    set id [object invoke Interpreter.GetActive NextId]

    set source [object invoke -flags +NonPublic -objectflags +NoDispose \
        Interpreter.GetActive.connections get_Item $srcDb]

    set code [compileCSharpWith [subst {
      using System;
      using System.Data.SQLite;
      using System.Text;

      namespace _Dynamic${id}
      {
        public static class Test${id}
        {
          public static void BackupAndGetData(
            SQLiteConnection source
            )
          {
            using (SQLiteConnection destination = new SQLiteConnection(
                "Data Source=:memory:;"))
            {
              destination.Open();
              source.BackupDatabase(destination, "main", "main", -1, null, 0);
            }
          }

          /////////////////////////////////////////////////////////////////////

          public static void Main()
          {
            // do nothing.
          }
        }
      }
    }] true true true results errors System.Data.SQLite.dll]
    if {$code eq "Ok"} then {
      object invoke _Dynamic${id}.Test${id} BackupAndGetData $source
    } else {
      error $errors
    }
    puts -nonewline stdout C; after [expr {int(rand() * 1000)}]
  }]

  #############################################################################

  set workload(13) [list [list srcDb fileName table count] {
    #
    # NOTE: Workload #13, backup from an in-memory database.
    #
    set id [object invoke Interpreter.GetActive NextId]

    set source [object invoke -flags +NonPublic -objectflags +NoDispose \
        Interpreter.GetActive.connections get_Item $srcDb]

    set code [compileCSharpWith [subst {
      using System;
      using System.Data.SQLite;
      using System.Text;

      namespace _Dynamic${id}
      {
        public static class Test${id}
        {
          public static void BackupAndGetData(
            SQLiteConnection source
            )
          {
            using (SQLiteConnection destination = new SQLiteConnection(
                "Data Source=${fileName};"))
            {
              destination.Open();
              source.BackupDatabase(destination, "main", "main", -1, null, 0);
            }
          }

          /////////////////////////////////////////////////////////////////////

          public static void Main()
          {
            // do nothing.
          }
        }
      }
    }] true true true results errors System.Data.SQLite.dll]
    if {$code eq "Ok"} then {
      object invoke _Dynamic${id}.Test${id} BackupAndGetData $source
    } else {
      error $errors
    }
    puts -nonewline stdout D; after [expr {int(rand() * 1000)}]
  }]
} -body {
  for {set index(0) 0} {$index(0) < $count(0)} {incr index(0)} {
    sql execute $db "CREATE TABLE IF NOT EXISTS t1(x PRIMARY KEY, y, z);"

    unset -nocomplain thread

    foreach index(1) [array names workload] {
      set thread($index(1)) [object create -alias System.Threading.Thread \
          [list apply $workload($index(1)) $srcDb $fileName(2) t1 $count(1)]]
    }

    foreach index(1) [array names thread] {
      $thread($index(1)) Start
    }

    foreach index(1) [array names thread] {
      $thread($index(1)) Join
    }
  }

  puts stdout ""
} -cleanup {
  cleanupDb $fileName(2)
  cleanupDb $fileName(1) srcDb

  unset -nocomplain thread index workload srcDb db fileName options count
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result {}}

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue