Annotation of embedaddon/sqlite3/test/lock_common.tcl, revision 1.1

1.1     ! misho       1: # 2010 April 14
        !             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: # This file contains code used by several different test scripts. The
        !            12: # code in this file allows testfixture to control another process (or
        !            13: # processes) to test locking.
        !            14: #
        !            15: 
        !            16: proc do_multiclient_test {varname script} {
        !            17: 
        !            18:   foreach code [list {
        !            19:     if {[info exists ::G(valgrind)]} { db close ; continue }
        !            20:     set ::code2_chan [launch_testfixture]
        !            21:     set ::code3_chan [launch_testfixture]
        !            22:     proc code2 {tcl} { testfixture $::code2_chan $tcl }
        !            23:     proc code3 {tcl} { testfixture $::code3_chan $tcl }
        !            24:     set tn 1
        !            25:   } {
        !            26:     proc code2 {tcl} { uplevel #0 $tcl }
        !            27:     proc code3 {tcl} { uplevel #0 $tcl }
        !            28:     set tn 2
        !            29:   }] {
        !            30:     faultsim_delete_and_reopen
        !            31: 
        !            32:     proc code1 {tcl} { uplevel #0 $tcl }
        !            33:   
        !            34:     # Open connections [db2] and [db3]. Depending on which iteration this
        !            35:     # is, the connections may be created in this interpreter, or in 
        !            36:     # interpreters running in other OS processes. As such, the [db2] and [db3]
        !            37:     # commands should only be accessed within [code2] and [code3] blocks,
        !            38:     # respectively.
        !            39:     #
        !            40:     eval $code
        !            41:     code2 { sqlite3 db2 test.db }
        !            42:     code3 { sqlite3 db3 test.db }
        !            43:     
        !            44:     # Shorthand commands. Execute SQL using database connection [db2] or 
        !            45:     # [db3]. Return the results.
        !            46:     #
        !            47:     proc sql1 {sql} { db eval $sql }
        !            48:     proc sql2 {sql} { code2 [list db2 eval $sql] }
        !            49:     proc sql3 {sql} { code3 [list db3 eval $sql] }
        !            50:   
        !            51:     proc csql1 {sql} { list [catch { sql1 $sql } msg] $msg }
        !            52:     proc csql2 {sql} { list [catch { sql2 $sql } msg] $msg }
        !            53:     proc csql3 {sql} { list [catch { sql3 $sql } msg] $msg }
        !            54: 
        !            55:     uplevel set $varname $tn
        !            56:     uplevel $script
        !            57: 
        !            58:     catch { code2 { db2 close } }
        !            59:     catch { code3 { db3 close } }
        !            60:     catch { close $::code2_chan }
        !            61:     catch { close $::code3_chan }
        !            62:     catch { db close }
        !            63:   }
        !            64: }
        !            65: 
        !            66: # Launch another testfixture process to be controlled by this one. A
        !            67: # channel name is returned that may be passed as the first argument to proc
        !            68: # 'testfixture' to execute a command. The child testfixture process is shut
        !            69: # down by closing the channel.
        !            70: proc launch_testfixture {{prg ""}} {
        !            71:   write_main_loop
        !            72:   if {$prg eq ""} { set prg [info nameofexec] }
        !            73:   if {$prg eq ""} { set prg testfixture }
        !            74:   if {[file tail $prg]==$prg} { set prg [file join . $prg] }
        !            75:   set chan [open "|$prg tf_main.tcl" r+]
        !            76:   fconfigure $chan -buffering line
        !            77:   set rc [catch { 
        !            78:     testfixture $chan "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
        !            79:   }]
        !            80:   if {$rc} {
        !            81:     testfixture $chan "set ::sqlite_pending_byte $::sqlite_pending_byte"
        !            82:   }
        !            83:   return $chan
        !            84: }
        !            85: 
        !            86: # Execute a command in a child testfixture process, connected by two-way
        !            87: # channel $chan. Return the result of the command, or an error message.
        !            88: #
        !            89: proc testfixture {chan cmd} {
        !            90:   puts $chan $cmd
        !            91:   puts $chan OVER
        !            92:   set r ""
        !            93:   while { 1 } {
        !            94:     set line [gets $chan]
        !            95:     if { $line == "OVER" } { 
        !            96:       set res [lindex $r 1]
        !            97:       if { [lindex $r 0] } { error $res }
        !            98:       return $res
        !            99:     }
        !           100:     if {[eof $chan]} {
        !           101:       return "ERROR: Child process hung up"
        !           102:     }
        !           103:     append r $line
        !           104:   }
        !           105: }
        !           106: 
        !           107: proc testfixture_nb_cb {varname chan} {
        !           108:   if {[eof $chan]} {
        !           109:     append ::tfnb($chan) "ERROR: Child process hung up"
        !           110:     set line "OVER"
        !           111:   } else {
        !           112:     set line [gets $chan]
        !           113:   }
        !           114: 
        !           115:   if { $line == "OVER" } {
        !           116:     set $varname [lindex $::tfnb($chan) 1]
        !           117:     unset ::tfnb($chan)
        !           118:     close $chan
        !           119:   } else {
        !           120:     append ::tfnb($chan) $line
        !           121:   }
        !           122: }
        !           123: 
        !           124: proc testfixture_nb {varname cmd} {
        !           125:   set chan [launch_testfixture]
        !           126:   set ::tfnb($chan) ""
        !           127:   fconfigure $chan -blocking 0 -buffering none
        !           128:   puts $chan $cmd
        !           129:   puts $chan OVER
        !           130:   fileevent $chan readable [list testfixture_nb_cb $varname $chan]
        !           131:   return ""
        !           132: }
        !           133: 
        !           134: # Write the main loop for the child testfixture processes into file
        !           135: # tf_main.tcl. The parent (this script) interacts with the child processes
        !           136: # via a two way pipe. The parent writes a script to the stdin of the child
        !           137: # process, followed by the word "OVER" on a line of its own. The child
        !           138: # process evaluates the script and writes the results to stdout, followed
        !           139: # by an "OVER" of its own.
        !           140: #
        !           141: set main_loop_written 0
        !           142: proc write_main_loop {} {
        !           143:   if {$::main_loop_written} return
        !           144:   set wrapper ""
        !           145:   if {[sqlite3 -has-codec] && [info exists ::do_not_use_codec]==0} {
        !           146:     set wrapper "
        !           147:       rename sqlite3 sqlite_orig
        !           148:       proc sqlite3 {args} {[info body sqlite3]}
        !           149:     "
        !           150:   }
        !           151: 
        !           152:   set fd [open tf_main.tcl w]
        !           153:   puts $fd [string map [list %WRAPPER% $wrapper] {
        !           154:     %WRAPPER%
        !           155:     set script ""
        !           156:     while {![eof stdin]} {
        !           157:       flush stdout
        !           158:       set line [gets stdin]
        !           159:       if { $line == "OVER" } {
        !           160:         set rc [catch {eval $script} result]
        !           161:         puts [list $rc $result]
        !           162:         puts OVER
        !           163:         flush stdout
        !           164:         set script ""
        !           165:       } else {
        !           166:         append script $line
        !           167:         append script "\n"
        !           168:       }
        !           169:     }
        !           170:   }]
        !           171:   close $fd
        !           172:   set main_loop_written 1
        !           173: }
        !           174: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>