set test "perf"

if {! [installtest_p]} { untested "$test"; return }
if {! [perf_probes_p]} { untested "$test"; return }

proc cleanup_handler { verbose } {
    catch {exec rm -f towers.x}
}

set stap_path $env(SYSTEMTAP_PATH)/stap
set exepath "[pwd]/towers.x"
set subtest "process()"

set res [target_compile $srcdir/$subdir/towers.c $exepath executable \
    "additional_flags=-O2 additional_flags=-g"]
if { $res != "" } {
    verbose "target_compile failed: $res" 2
    fail "$test compiling towers.c"
    cleanup_handler $verbose
    return
} else {
    pass "$test compiling towers.c"
}

spawn $stap_path $srcdir/$subdir/perf01.stp $exepath -c $exepath

# there is no "XXX" process so this probe should have been ignored
set ok 0
set compile_errors 0
expect {
    -timeout 180
    -re {^towers_n=0x[0-9a-f]{2,}\r\n} { incr ok; exp_continue }
    -re {^XXX_n=0x0\r\n} { incr ok; exp_continue }
    -re {^parse error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue }
    -re {^[^\r\n]*compilation failed[^\r\n]*\r\n} {
	incr compile_errors 1; exp_continue }
    -re {^semantic error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue }
    timeout { fail "$test (timeout)" }
    eof { }
}
catch {close}; catch {wait}

if {$ok == 2 && $compile_errors == 0} {
    pass "$test $subtest"
} else {
    fail "$test $subtest ($ok - $compile_errors)"
}

set subtest "process"

spawn $stap_path $srcdir/$subdir/perf02.stp -c $exepath

set ok 0
set compile_errors 0
expect {
    -timeout 180
    -re {^towers_n=0x[0-9a-f]{2,}\r\n} { incr ok; exp_continue }
    -re {^parse error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue }
    -re {^[^\r\n]*compilation failed[^\r\n]*\r\n} {
	incr compile_errors 1; exp_continue }
    -re {^semantic error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue }
    timeout { fail "$test (timeout)" }
    eof { }
}
catch {close}; catch {wait}

if {$ok == 1 && $compile_errors == 0} {
    pass "$test $subtest"
} else {
    fail "$test $subtest ($ok - $compile_errors)"
}

set subtest "counter"

target_compile $srcdir/$subdir/towers.c $exepath executable "additional_flags=-g"

if {! [uprobes_p]} {
    untested "$test $subtest"
} else {
    spawn $stap_path $srcdir/$subdir/perf03.stp $exepath -c $exepath

    set ok 0
    set compile_errors 0
    set hw_perf_probes 1
    expect {
	-timeout 180
	-re {^count main=1\r\n} { incr ok; exp_continue }
	-re {^count towers=500\r\n} { incr ok; exp_continue }
	-re {^min main=[\-0-9]+\r\n} { incr ok; exp_continue }
	-re {^min towers=[\-0-9]+\r\n} { incr ok; exp_continue }
	-re {^max main=[0-9]+\r\n} { incr ok; exp_continue }
	-re {^max towers=[0-9]+\r\n} { incr ok; exp_continue }
	-re {^WARNING:[^\r]*not supported by this kernel[^\r]*\r\n} {
	    # If this type of hardware perf probe isn't supported by
	    # this kernel, kfail the test. Remember this kfail, and
	    # try again with a software perf probe.
	    set hw_perf_probes 0; setup_kfail 15727 *-*-*; exp_continue }
	-re {^parse error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue }
	-re {^[^\r\n]*compilation failed[^\r\n]*\r\n} {
	    incr compile_errors 1; exp_continue }
	-re {^semantic error[^\r\n]*\r\n} { incr compile_errors 1;
	    exp_continue }
	timeout { fail "$test (timeout)" }
	eof { }
    }
    catch {close}; catch {wait}

    spawn $stap_path -W $srcdir/$subdir/perf04.stp $exepath -c $exepath

    expect {
	-timeout 180
	-re {^count main=1\r\n} { incr ok; exp_continue }
	timeout { fail "$test (timeout)" }
	eof { }
    }
    catch {close}; catch {wait}

    if {$ok == 7 && $compile_errors == 0} {
	pass "$test $subtest"
    } else {
	fail "$test $subtest ($ok - $compile_errors)"
    }

    if {! $hw_perf_probes} {
	set subtest "counter (sw)"
	spawn $stap_path $srcdir/$subdir/perf03sw.stp $exepath -c $exepath

	set ok 0
	set compile_errors 0
	expect {
	    -timeout 180
	    -re {^count main=1\r\n} { incr ok; exp_continue }
	    -re {^count towers=500\r\n} { incr ok; exp_continue }
	    -re {^min main=[\-0-9]+\r\n} { incr ok; exp_continue }
	    -re {^min towers=[\-0-9]+\r\n} { incr ok; exp_continue }
	    -re {^max main=[0-9]+\r\n} { incr ok; exp_continue }
	    -re {^max towers=[0-9]+\r\n} { incr ok; exp_continue }
	    -re {^parse error[^\r\n]*\r\n} {
		incr compile_errors 1; exp_continue }
	    -re {^[^\r\n]*compilation failed[^\r\n]*\r\n} {
		incr compile_errors 1; exp_continue }
	    -re {^semantic error[^\r\n]*\r\n} { incr compile_errors 1;
		exp_continue }
	    timeout { fail "$test (timeout)" }
	    eof { }
	}
	catch {close}; catch {wait}

	spawn $stap_path -W $srcdir/$subdir/perf04sw.stp $exepath -c $exepath

	expect {
	    -timeout 180
	    -re {^count main=1\r\n} { incr ok; exp_continue }
	    timeout { fail "$test (timeout)" }
	    eof { }
	}
	catch {close}; catch {wait}

	if {$ok == 7 && $compile_errors == 0} {
	    pass "$test $subtest"
	} else {
	    fail "$test $subtest ($ok - $compile_errors)"
	}
    }
}

set subtest "global"

spawn $stap_path $srcdir/$subdir/perf05.stp

set ok 0
set compile_errors 0
expect {
    -timeout 180
    -re {^hit=0x1\r\n} { incr ok; exp_continue }
    -re {^parse error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue }
    -re {^[^\r\n]*compilation failed[^\r\n]*\r\n} {
	incr compile_errors 1; exp_continue }
    -re {^semantic error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue }
    timeout { fail "$test (timeout)" }
    eof { }
}
catch {close}; catch {wait}

if {$ok == 1 && $compile_errors == 0} {
    pass "$test $subtest"
} else {
    fail "$test $subtest ($ok - $compile_errors)"
}

set subtest "counter order"

spawn $srcdir/$subdir/perf.sh $stap_path

expect {
    -timeout 180
    -re {PASS: [0-9 ]+} { regexp " .*$" $expect_out(0,string) s; 
        pass "$subtest $s"; exp_continue }
    -re {UNRESOLVED: [0-9 ]+} { regexp " .*$" $expect_out(0,string) s; 
        unresolved "$subtest $s"; exp_continue }
    -re {FAIL: [0-9 ]+} { regexp " .*$" $expect_out(0,string) s; 
        fail "$subtest $s"; exp_continue }
    timeout { fail "$test (timeout)" }
    eof { }
}
catch {close}; catch {wait}

cleanup_handler $verbose
