# Test the private keyword feature

set test "private"

# Setup
file mkdir "$test"
file copy "$srcdir/$subdir/${test}.stp" "$test"
cd "$test"

foreach runtime [get_runtime_list] {
    if {$runtime == ""} {set runtime kernel}

    # Subtest
    set subtest "$test private-variable-basic"
    set __counter 0
    eval spawn "stap --runtime=$runtime -I . -e {probe oneshot \{println(gtest1_getter(), \",\", gtest2_getter())\}}"
    expect {
        -timeout 160
        -re {^3,7\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    set subtest "$test private-variable-illegal-access"
    set __counter 0
    eval spawn "stap --runtime=$runtime -I . -e {probe oneshot \{println(gtest1)\}}"
    expect {
        -timeout 160
        -re {semantic error: unresolved type : identifier 'gtest1'} {
            incr __counter
            exp_continue
        }
        -re {^[^\r\n]+\r\n} {
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}


    # Subtest
    set subtest "$test private-function-basic"
    set __counter 0
    eval spawn "stap --runtime=$runtime -I . -e {probe oneshot \{println(getthree())\}}"
    expect {
        -timeout 160
        -re {^3\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    set subtest "$test private-function-illegal-access"
    set __counter 0
    eval spawn "stap --runtime=$runtime -I . -e {probe oneshot \{println(three())\}}"
    expect {
        -timeout 160
        -re {semantic error: unresolved function[^\r\n]+identifier 'three' at} {
            incr __counter
            exp_continue
        }
        -re {^[^\r\n]+\r\n} {
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    set subtest "$test global-variable-access"
    set __counter 0
    eval spawn "stap --runtime=$runtime -I . -e {probe oneshot \{println(myglobal)\}}"
    expect {
        -timeout 160
        -re {^11\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    set subtest "$test global-variable-access-override"
    set __counter 0
    eval spawn "stap --runtime=$runtime -G myglobal=12 -I . -e {probe oneshot \{println(myglobal)\}}"
    expect {
        -timeout 160
        -re {^12\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    # NB: Some kernels fail to load the module, but some just printk that
    # they're ignoring unknown parameters and continue anyway.  stapdyn also
    # just warns and continues, so treat either hard error or unmodified pt
    # output as a test PASS.
    set subtest "$test private-variable-override-denied"
    set __counter 0
    eval spawn "stap --runtime=$runtime -G pt=12 -e {private pt=13; probe oneshot \{println(pt)\}}"
    expect {
        -timeout 160
        -re {^ERROR: Couldn't insert module[^\r\n]+Unknown symbol in module\r\n} {
            incr __counter
            exp_continue
        }
        -re {^stapdyn: WARNING: Ignoring unknown module option 'pt'\r\n} {
            exp_continue
        }
        -re {^13\r\n} {
            incr __counter
            exp_continue
        }
        -re {^[^\r\n]+\r\n} {
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    set subtest "$test private-function-in-user-script"
    set __counter 0
    eval spawn "stap --runtime=$runtime -e {private function foo() { println(42) } probe oneshot \{ foo() \}}"
    expect {
        -timeout 160
        -re {^42\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    set subtest "$test multiple-private-global-var-decl"
    set __counter 0
    eval spawn "stap --runtime=$runtime -e {private varA = 41, varB = 42 probe oneshot \{ println(varA, varB) \}}"
    expect {
        -timeout 160
        -re {^4142\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    if {$runtime != "dyninst"} {
        set subtest "$test PR13721-workaround-test"
        set __counter 0
        eval spawn "stap --runtime=$runtime -e {private addr probe begin\{addr\[AF_INET()\]=\"addr\" exit()\}}"
        expect {
            -timeout 160
            -re {^addr\[2\]="addr"\r\n} {
                incr __counter
                exp_continue
            }
            timeout {fail "$subtest (timeout)"}
        }
        catch {close}; catch {wait}
        if {$__counter == 1} {pass $subtest} else {fail $subtest}
    }

    # Subtest
    # PR20307 Make sure a private global variable (defined in a tapset)
    # is resolvable within a probe alias (from that same tapset).
    set subtest "$test PR20307-private-variable-in-tapset-probe-alias"
    set __counter 0
    eval spawn "stap --runtime=$runtime -I . -e {probe foo \{println(f) exit()\}}"
    expect {
        -timeout 160
        -re {^7\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}

    # Subtest
    # Analogy to the above, but for a private global function.
    set subtest "$test private-function-in-tapset-probe-alias"
    set __counter 0
    eval spawn "stap --runtime=$runtime -I . -e {probe bar \{println(g) exit()\}}"
    expect {
        -timeout 160
        -re {^3\r\n} {
            incr __counter
            exp_continue
        }
        timeout {fail "$subtest (timeout)"}
    }
    catch {close}; catch {wait}
    if {$__counter == 1} {pass $subtest} else {fail $subtest}
}

# Cleanup
cd ..
file delete -force "$test"
