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

     1  # 2008 August 27
     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 implements regression tests for SQLite library.  The
    13  # focus of this script is transactions
    14  #
    15  # $Id: trans2.test,v 1.1 2008/08/27 18:56:36 drh Exp $
    16  #
    17  set testdir [file dirname $argv0]
    18  source $testdir/tester.tcl
    19  
    20  # A procedure to scramble the elements of list $inlist into a random order.
    21  #
    22  proc scramble {inlist} {
    23    set y {}
    24    foreach x $inlist {
    25      lappend y [list [expr {rand()}] $x]
    26    }
    27    set y [lsort $y]
    28    set outlist {}
    29    foreach x $y {
    30      lappend outlist [lindex $x 1]
    31    }
    32    return $outlist
    33  }
    34  
    35  # Generate a UUID using randomness.
    36  #
    37  expr srand(1)
    38  proc random_uuid {} {
    39    set u {}
    40    for {set i 0} {$i<5} {incr i} {
    41      append u [format %06x [expr {int(rand()*16777216)}]]
    42    }
    43    return $u
    44  }
    45  
    46  # Compute hashes on the u1 and u2 fields of the sample data.
    47  #
    48  proc hash1 {} {
    49    global data
    50    set x ""
    51    foreach rec [lsort -integer -index 0 $data] {
    52      append x [lindex $rec 1]
    53    }
    54    return [md5 $x]
    55  }
    56  proc hash2 {} {
    57    global data
    58    set x ""
    59    foreach rec [lsort -integer -index 0 $data] {
    60      append x [lindex $rec 3]
    61    }
    62    return [md5 $x]
    63  }
    64  
    65  # Create the initial data set
    66  #
    67  unset -nocomplain data i max_rowid todel n rec max1 id origres newres
    68  unset -nocomplain inssql modsql s j z
    69  set data {}
    70  for {set i 0} {$i<400} {incr i} {
    71    set rec [list $i [random_uuid] [expr {int(rand()*5000)+1000}] [random_uuid]]
    72    lappend data $rec
    73  }
    74  set max_rowid [expr {$i-1}]
    75  
    76  # Create the T1 table used to hold test data.  Populate that table with
    77  # the initial data set and check hashes to make sure everything is correct.
    78  #
    79  do_test trans2-1.1 {
    80    execsql {
    81      PRAGMA cache_size=100;
    82      CREATE TABLE t1(
    83        id INTEGER PRIMARY KEY,
    84        u1 TEXT UNIQUE,
    85        z BLOB NOT NULL,
    86        u2 TEXT UNIQUE
    87      );
    88    }
    89    foreach rec [scramble $data] {
    90      foreach {id u1 z u2} $rec break
    91      db eval {INSERT INTO t1 VALUES($id,$u1,zeroblob($z),$u2)}
    92    }
    93    db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
    94  } [list [hash1] [hash2]]
    95  
    96  # Repeat the main test loop multiple times.
    97  #
    98  for {set i 2} {$i<=30} {incr i} {
    99    # Delete one row out of every 10 in the database.  This will add
   100    # many pages to the freelist.
   101    #
   102    set todel {}
   103    set n [expr {[llength $data]/10}]
   104    set data [scramble $data]
   105    foreach rec [lrange $data 0 $n] {
   106      lappend todel [lindex $rec 0]
   107    }
   108    set data [lrange $data [expr {$n+1}] end]
   109    set max1 [lindex [lindex $data 0] 0]
   110    foreach rec $data {
   111      set id [lindex $rec 0]
   112      if {$id>$max1} {set max1 $id}
   113    }
   114    set origres [list [hash1] [hash2]]
   115    do_test trans2-$i.1 {
   116      db eval "DELETE FROM t1 WHERE id IN ([join $todel ,])"
   117      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   118    } $origres
   119    integrity_check trans2-$i.2
   120  
   121    # Begin a transaction and insert many new records.
   122    #
   123    set newdata {}
   124    foreach id $todel {
   125      set rec [list $id [random_uuid] \
   126                        [expr {int(rand()*5000)+1000}] [random_uuid]]
   127      lappend newdata $rec
   128      lappend data $rec
   129    }
   130    for {set j 1} {$j<50} {incr j} {
   131      set id [expr {$max_rowid+$j}]
   132      lappend todel $id
   133      set rec [list $id [random_uuid] \
   134                        [expr {int(rand()*5000)+1000}] [random_uuid]]
   135      lappend newdata $rec
   136      lappend data $rec
   137    }
   138    set max_rowid [expr {$max_rowid+$j-1}]
   139    set modsql {}
   140    set inssql {}
   141    set newres [list [hash1] [hash2]]
   142    do_test trans2-$i.3 {
   143      db eval BEGIN
   144      foreach rec [scramble $newdata] {
   145        foreach {id u1 z u2} $rec break
   146        set s "INSERT INTO t1 VALUES($id,'$u1',zeroblob($z),'$u2');"
   147        append modsql $s\n
   148        append inssql $s\n
   149        db eval $s
   150      }
   151      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   152    } $newres
   153    integrity_check trans2-$i.4
   154  
   155    # Do a large update that aborts do to a constraint failure near
   156    # the end.  This stresses the statement journal mechanism.
   157    #
   158    do_test trans2-$i.10 {
   159      catchsql {
   160        UPDATE t1 SET u1=u1||'x',
   161            z = CASE WHEN id<$max_rowid
   162                     THEN zeroblob((random()&65535)%5000 + 1000) END;
   163      }
   164    } {1 {NOT NULL constraint failed: t1.z}}
   165    do_test trans2-$i.11 {
   166      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   167    } $newres
   168  
   169    # Delete all of the newly inserted records.  Verify that the database
   170    # is back to its original state.
   171    #
   172    do_test trans2-$i.20 {
   173      set s "DELETE FROM t1 WHERE id IN ([join $todel ,]);"
   174      append modsql $s\n
   175      db eval $s
   176      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   177    } $origres
   178  
   179    # Do another large update that aborts do to a constraint failure near
   180    # the end.  This stresses the statement journal mechanism.
   181    #
   182    do_test trans2-$i.30 {
   183      catchsql {
   184        UPDATE t1 SET u1=u1||'x',
   185            z = CASE WHEN id<$max1
   186                     THEN zeroblob((random()&65535)%5000 + 1000) END;
   187      }
   188    } {1 {NOT NULL constraint failed: t1.z}}
   189    do_test trans2-$i.31 {
   190      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   191    } $origres
   192  
   193    # Redo the inserts
   194    #
   195    do_test trans2-$i.40 {
   196      db eval $inssql
   197      append modsql $inssql
   198      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   199    } $newres
   200  
   201    # Rollback the transaction.  Verify that the content is restored.
   202    #
   203    do_test trans2-$i.90 {
   204      db eval ROLLBACK
   205      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   206    } $origres
   207    integrity_check trans2-$i.91
   208  
   209    # Repeat all the changes, but this time commit.
   210    #
   211    do_test trans2-$i.92 {
   212      db eval BEGIN
   213      catchsql {
   214        UPDATE t1 SET u1=u1||'x',
   215            z = CASE WHEN id<$max1
   216                     THEN zeroblob((random()&65535)%5000 + 1000) END;
   217      }
   218      db eval $modsql
   219      catchsql {
   220        UPDATE t1 SET u1=u1||'x',
   221            z = CASE WHEN id<$max1
   222                     THEN zeroblob((random()&65535)%5000 + 1000) END;
   223      }
   224      db eval COMMIT
   225      db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id}
   226    } $newres
   227    integrity_check trans2-$i.93
   228  }
   229  
   230  unset -nocomplain data i max_rowid todel n rec max1 id origres newres
   231  unset -nocomplain inssql modsql s j z
   232  finish_test