set stapi_prompt "stap>" set stapi_spawn_id 0 # stapi_start ARGS # # Start "stap -i" with ARGS. # # ARGS are the optional additional arguments to pass to systemtap. # # Returns: # 1 if starting systemtap failed, # 0 if systemtap was started. proc stapi_start { {args ""} } { global stapi_spawn_id global spawn_id if {[info exists stapi_spawn_id] && $stapi_spawn_id != 0} { return } if {![string match "" $args]} { set rc [catch {spawn stap -i $args} out] } else { set rc [catch {spawn stap -i} out] } if {$rc} { verbose -log "$out" fail "Couldn't start \"stap -i\"" return 1 } pass "Started stap -i" set stapi_spawn_id $spawn_id # If the pathnames given to the interactive stap's 'load' command # are long, then readline will try to scroll them, causing lots of # control characters in the output. This confuses us when reading # the output. Instead of trying to interpret the control # characters, just lie and tell the system stap's terminal is # *really* wide, to avoid the need to scroll. stty columns 4096 < $spawn_out(slave,name) return 0 } # stapi_exit # # Finish up the interactive systemtap. proc stapi_exit { } { global stapi_spawn_id if {![info exists stapi_spawn_id] || $stapi_spawn_id == 0} { return } catch { send -i $stapi_spawn_id "quit\n" expect { -timeout 5 timeout { verbose -log "quit timeout"; kill -INT -[exp_pid] } eof { } } } # again for good measure with KILL after 3s kill -INT -[exp_pid -i $stapi_spawn_id] 3 catch {close}; catch {wait} set stapi_spawn_id 0 } # stapi_test_no_output COMMAND MESSAGE # # Send a command to GDB and verify that this command generated no output. # # COMMAND is the command to execute. # MESSAGE is the message to be used in a pass/fail text. If MESSAGE is # empty, no pass/fail will be reported. # # Returns: # 1 if the test failed, # 0 if the test passes. # -1 if there was an internal error. proc stapi_test_no_output { command {message ""} } { global stapi_prompt global stapi_spawn_id set rc 1 verbose -log "Sending \"$command\" to stapi" if {! [info exists stapi_spawn_id]} { return } send -i $stapi_spawn_id "$command\n" expect { -timeout 5 -re "(${command}\r\n$stapi_prompt )$" { set rc 0 } eof { verbose -log "\"$command\" EOF"; set rc -1 } timeout { verbose -log "\"$command\" timeout" } } if {![string match "" $message]} { if {!$rc} { pass "$message" } elseif {$rc < 0} { fail "$message (EOF)" } else { fail "$message" } } return $rc } # stapi_test_question COMMAND QUESTION RESPONSE MESSAGE # # Send a command to interactive stap (stap -i); expect a question, and # send an answer. # # COMMAND is the command to execute. # QUESTION is a question interactive stap may ask in response to # COMMAND, like "are you sure?" # RESPONSE is the response to send when QUESTION appears. # MESSAGE is the message to be used in a pass/fail text. If MESSAGE is # empty, no pass/fail will be reported. # # Returns: # 1 if the test failed, # 0 if the test passes. # -1 if there was an internal error. proc stapi_test_question { command question response {message ""} } { global stapi_prompt global stapi_spawn_id set rc 0 verbose -log "Sending \"$command\" to stapi" send -i $stapi_spawn_id "$command\n" expect { -timeout 5 -re "(${question})$" { send -i $stapi_spawn_id "$response\n" incr rc exp_continue } -re "($response\r\n$stapi_prompt )$" { incr rc } eof { verbose -log "\"$command\" EOF"; set rc -1 } timeout { verbose -log "\"$command\" timeout" } } if {$rc == 2} { set rc 0 } elseif {$rc > 0} { set rc 1 } if {![string match "" $message]} { if {!$rc} { pass "$message" } elseif {$rc < 0} { fail "$message (EOF)" } else { fail "$message" } } return $rc } # stapi_run_batch USE_CACHE # # Call "run" in interactive systemtap to compile a script. This code # is somewhat analagous to stap_run_batch() in # testsuite/lib/systemtap.exp. # # USE_CACHE is set to 0 to indicate the cache should not have been # used when compiling, 1 for cache use. # # Returns: # 2 if the script compiled, but the cache wasn't used appropriately. # 1 if the script couldn't be compiled. # 0 if the test passes. # -1 if there was an internal error. # -2 if there was a timeout error. proc stapi_run_batch { {use_cache 0} } { global stapi_prompt global stapi_spawn_id verbose -log "Sending \"run\" to stapi" send -i $stapi_spawn_id "run\n" set rc 0 set error_seen 0 set cache_used 0 set eof_seen 0 set timeout_seen 0 expect { -timeout 600 -re "compilation failed" { set error_seen 1; exp_continue } -re "semantic error:" { set error_seen 1; exp_continue } -re {Pass\ ([1234]):[^\r]*\ in\ ([0-9]+)usr/([0-9]+)sys/([0-9]+)real\ ms\.\r\n} { incr rc; exp_continue } -re {Pass\ ([34]): using cached [^\r]+\r\n} { set cache_used 1 incr rc; exp_continue } -re {Passes: via server [^\r]* using [^\r]* in [0-9]+usr/[0-9]+sys/[0-9]+real ms\.\r\n} { exp_continue } -re "$stapi_prompt" { # If this is the prompt after the script has been compiled # (we've seen some/all of the "Pass [1234]" lines, then we # can quit (by not calling 'exp_continue'). if {$rc > 0} { incr rc } else { exp_continue } } eof { verbose -log "stapi_run_batch EOF"; set eof_seen 1 } timeout { verbose -log "stapi_run_batch timeout" set timeout_seen 1 } } if {$eof_seen} { return -1 } elseif {$timeout_seen} { return -2 } elseif {$rc != 5 || $error_seen} { return 1 } # If rc == 5, we've seen 4 "Pass [1234]" lines and then the stap # prompt, the compilation worked. # # But, even if the script compiled correctly, was the cache used # (or not) correctly? if {$cache_used == $use_cache} { return 0 } return 2 }