# Utrace run (pass 5) tests.

# Initialize variables
set exepath "[pwd]/cat_[pid]"
set multi_srcpath "$srcdir/systemtap.base/utrace_p5_multi.c"
set multi_exepath "[pwd]/utrace_p5_multi_[pid]"
set multi_flags "libs=-lpthread"

set end_script {
    global end_probes_fired = 0
    probe begin { printf("systemtap starting probe\n") }
    probe process("%s").end { end_probes_fired++ }
    probe end { printf("systemtap ending probe\n")
	printf("end probes = %%d\n", end_probes_fired) }
}
set end_script_output "end probes = 1\r\n"

set begin_script {
    global begin_probes_fired = 0
    probe begin { printf("systemtap starting probe\n") }
    probe process("%s").begin { begin_probes_fired++ }
    probe end { printf("systemtap ending probe\n")
	printf("begin probes = %%d\n", begin_probes_fired) }
}
set begin_script_output "begin probes = 1\r\n"

set syscall_script {
    global syscall_probes_fired = 0
    probe begin { printf("systemtap starting probe\n") }
    probe process("%s").syscall { syscall_probes_fired++ }
    probe end { printf("systemtap ending probe\n")
	if (syscall_probes_fired > 0) {
	    printf("syscalls = %%d\n", syscall_probes_fired)
	}
    }
}
set syscall_script_output "syscalls = \\d+\r\n"

set syscall_return_script {
    global syscall_return_probes_fired = 0
    probe begin { printf("systemtap starting probe\n") }
    probe process("%s").syscall.return { syscall_return_probes_fired++ }
    probe end { printf("systemtap ending probe\n")
	if (syscall_return_probes_fired > 0) {
	    printf("syscall_returns = %%d\n", syscall_return_probes_fired)
	}
    }
}
set syscall_return_script_output "syscall_returns = \\d+\r\n"

set thread_begin_script {
    global thread_begin_probes_fired = 0
    probe begin { printf("systemtap starting probe\n") }
    probe process("%s").thread.begin { thread_begin_probes_fired++ }
    probe end { printf("systemtap ending probe\n")
	if (thread_begin_probes_fired > 0) {
	    printf("thread_begins = %%d\n", thread_begin_probes_fired)
	}
    }
}
set thread_begin_script_output "thread_begins = \\d+\r\n"

set thread_end_script {
    global thread_end_probes_fired = 0
    probe begin { printf("systemtap starting probe\n") }
    probe process("%s").thread.end { thread_end_probes_fired++ }
    probe end { printf("systemtap ending probe\n")
	if (thread_end_probes_fired > 0) {
	    printf("thread_ends = %%d\n", thread_end_probes_fired)
	}
    }
}
set thread_end_script_output "thread_ends = \\d+\r\n"

# Script that tests the bug 6841 fix.
set bz6841_script {
    global proc,name
    probe begin { printf("systemtap starting probe\n") }
    probe process.syscall {
	proc[pid()] <<< 1
	name[pid()] = execname()
    }
    probe end { printf("systemtap ending probe\n")
	foreach(p+ in proc) {
	    printf("%s(%d) issues syscall %d times\n",
		   name[p], p, @sum(proc[p]))
	}
    }
}
set bz6841_script_output ".+ issues syscall \\d+ times\r\n"

set syscall_parms_script {
    global syscall_parms_string
    probe begin { printf("systemtap starting probe\n") }
    probe process.syscall { syscall_parms_string = $$parms exit() }
    probe end { printf("systemtap ending probe\n")
	        printf("%s\n",syscall_parms_string)
		delete syscall_parms_string
              }
}
set syscall_parms_script_output "(.+arg\[1-6\]=0x\[0-9a-f\]+)+\r\n"


# Set up our own copy of /bin/cat, to make testing for a particular
# executable easy.  We can't use 'ln' here, since we might be creating
# a cross-device link.  We can't use 'ln -s' here, since the kernel
# resolves the symbolic link and reports that /bin/cat is being
# exec'ed (instead of our local copy).
if {[catch {exec cp /bin/cat $exepath} res]} {
    fail "unable to copy /bin/cat: $res"
    return
}

# "load" generation function for stap_run.  It spawns our own copy of
# /bin/cat, waits 5 seconds, then kills it.
proc run_cat_5_sec {} {
    global exepath

    spawn $exepath
    set exe_id $spawn_id
    after 5000;
    exec kill -INT -- -[exp_pid -i $exe_id]
    catch {close -i $exe_id}
    catch {wait -i $exe_id}
    return 0;
}

# Compile our multi-threaded test program.
set res [target_compile $multi_srcpath $multi_exepath executable $multi_flags]
if { $res != "" } {
    verbose "target_compile failed: $res" 2
    fail "unable to compile $multi_srcpath"
    return
}

# "load" generation function for stap_run.  It spawns our
# multi-threaded test program and waits for it to finish. 
proc run_utrace_p5_multi {} {
    global multi_exepath

    if {[catch {exec $multi_exepath} res]} {
	verbose "unable to run $multi_exepath: $res"
    }
    return 0;
}

set TEST_NAME "UTRACE_P5_01"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $end_script $exepath]
    stap_run $TEST_NAME run_cat_5_sec $end_script_output -e $script
}

set TEST_NAME "UTRACE_P5_01_cmd"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $end_script $exepath]
    foreach runtime [get_runtime_list] {
	set test "$TEST_NAME"
	if {$runtime != ""} {
	    set test "${test}_${runtime}"
	    stap_run $test wait_5_secs $end_script_output \
		-e $script --runtime=$runtime -c "$exepath /dev/null"
	} else {
	    stap_run $test wait_5_secs $end_script_output \
		-e $script -c "$exepath /dev/null"
	}
    }
}

set TEST_NAME "UTRACE_P5_02"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $begin_script $exepath]
    stap_run $TEST_NAME run_cat_5_sec $begin_script_output -e $script
}

set TEST_NAME "UTRACE_P5_02_cmd"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $begin_script $exepath]
    foreach runtime [get_runtime_list] {
	set test "$TEST_NAME"
	if {$runtime != ""} {
	    set test "${test}_${runtime}"
	    stap_run $test wait_5_secs $begin_script_output \
		-e $script --runtime=$runtime -c "$exepath /dev/null"
	} else {
	    stap_run $test wait_5_secs $begin_script_output \
		-e $script -c "$exepath /dev/null"
	}
    }
}

set TEST_NAME "UTRACE_P5_03"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $syscall_script $exepath]
    stap_run $TEST_NAME run_cat_5_sec $syscall_script_output -e $script
}

set TEST_NAME "UTRACE_P5_04"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $syscall_return_script $exepath]
    stap_run $TEST_NAME run_cat_5_sec $syscall_return_script_output -e $script
}

set TEST_NAME "UTRACE_P5_05"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $thread_begin_script $multi_exepath]
    stap_run $TEST_NAME run_utrace_p5_multi $thread_begin_script_output \
	-e $script
}

set TEST_NAME "UTRACE_P5_05_cmd"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $thread_begin_script $multi_exepath]
    foreach runtime [get_runtime_list] {
	set test "$TEST_NAME"
	if {$runtime != ""} {
	    set test "${test}_${runtime}"
	    stap_run $test wait_5_secs $thread_begin_script_output \
		-e $script --runtime=$runtime -c $multi_exepath
	} else {
	    stap_run $test wait_5_secs $thread_begin_script_output \
		-e $script -c $multi_exepath
	}
    }
}

set TEST_NAME "UTRACE_P5_06"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $thread_end_script $multi_exepath]
    stap_run $TEST_NAME run_utrace_p5_multi $thread_end_script_output \
	-e $script
}

set TEST_NAME "UTRACE_P5_06_cmd"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $thread_end_script $multi_exepath]
    foreach runtime [get_runtime_list] {
	set test "$TEST_NAME"
	if {$runtime != ""} {
	    set test "${test}_${runtime}"
	    stap_run $test wait_5_secs $thread_end_script_output \
		-e $script --runtime=$runtime -c $multi_exepath
	} else {
	    stap_run $test wait_5_secs $thread_end_script_output \
		-e $script -c $multi_exepath
	}
    }
}

set TEST_NAME "UTRACE_P5_07"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    stap_run $TEST_NAME run_utrace_p5_multi $bz6841_script_output \
	-e $bz6841_script
}

set TEST_NAME "UTRACE_P5_08"
if {![utrace_p]} {
    untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
    untested "$TEST_NAME"
} else {
    set script [format $syscall_parms_script "%s"]
    stap_run $TEST_NAME no_load $syscall_parms_script_output -e $script
}

# Cleanup
exec rm -f $exepath $multi_exepath
