Bash · 4046 bytes Raw Blame History
1 #!/bin/sh
2 TEST_PREFIX="[int-scope-env]"
3 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4 SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5 export SHELL_BIN
6 . "$SCRIPT_DIR/../test_harness.sh"
7
8 # Integration tests: variable scope, export, source, environment inheritance
9
10 section "1. export inheritance"
11 compare_output "exported var in subshell" 'export SEX=hello; (echo $SEX)'
12 compare_output "non-exported not in subshell cmd" 'SEX2=hello; echo ${SEX2:-unset}'
13 compare_output "export from function" 'f() { export SEF=val; }; f; echo $SEF'
14 compare_output "export -n removes export" 'export SEN=val; export -n SEN; echo $SEN'
15 compare_output "export with value" 'export SEV=hello; echo $SEV'
16 compare_output "export existing var" 'SEE=existing; export SEE; echo $SEE'
17
18 section "2. source/dot scope"
19 compare_output "var from source" "echo 'SSV=sourced' > $TEST_TMPDIR/scope1.sh; source $TEST_TMPDIR/scope1.sh; echo \$SSV"
20 compare_output "source overwrites var" "X_SC=before; echo 'X_SC=after' > $TEST_TMPDIR/scope2.sh; source $TEST_TMPDIR/scope2.sh; echo \$X_SC"
21 compare_output "return from source" "echo 'return 42' > $TEST_TMPDIR/scope3.sh; source $TEST_TMPDIR/scope3.sh; echo \$?"
22 compare_output "cd from source" "echo 'cd /tmp' > $TEST_TMPDIR/scope4.sh; ORIG=\$(pwd); source $TEST_TMPDIR/scope4.sh; pwd; cd \"\$ORIG\""
23 compare_output "function def from source" "echo 'sf() { echo sourced_func; }' > $TEST_TMPDIR/scope5.sh; source $TEST_TMPDIR/scope5.sh; sf"
24 compare_output "multiple source" "echo 'A_SC=1' > $TEST_TMPDIR/scope6a.sh; echo 'B_SC=2' > $TEST_TMPDIR/scope6b.sh; source $TEST_TMPDIR/scope6a.sh; source $TEST_TMPDIR/scope6b.sh; echo \$A_SC \$B_SC"
25 compare_output "source with args" "echo 'echo \$1 \$2' > $TEST_TMPDIR/scope7.sh; source $TEST_TMPDIR/scope7.sh hello world"
26 compare_output "dot command same as source" "echo 'DSV=dotted' > $TEST_TMPDIR/scope8.sh; . $TEST_TMPDIR/scope8.sh; echo \$DSV"
27
28 section "3. eval scope"
29 compare_output "eval modifies scope" 'eval "ESV=from_eval"; echo $ESV'
30 compare_output "eval export" 'eval "export ESE=eval_export"; echo $ESE'
31 compare_output "eval readonly" 'eval "readonly ESR=eval_readonly"; echo $ESR'
32 compare_output "eval function def" 'eval "esf() { echo eval_func; }"; esf'
33 compare_output "eval preserves vars" 'X_EV=before; eval "echo \$X_EV"'
34 compare_output "nested eval" 'eval "eval \"echo nested_eval\""'
35
36 section "4. declare -g"
37 compare_output "declare -g from function" 'f() { declare -g DGV=global_val; }; f; echo $DGV'
38 compare_output "declare without -g stays local" 'f() { declare DLV=local_val; }; f; echo ${DLV:-unset}'
39 compare_output "declare -g overwrites" 'DGO=old; f() { declare -g DGO=new; }; f; echo $DGO'
40
41 section "5. IFS manipulation scope"
42 compare_output "IFS in function local" 'f() { local IFS=:; read A B <<< "x:y"; echo $A $B; }; f; echo "${IFS:-default}" | cat -v'
43 compare_output "IFS change persists" 'IFS=:; read A B <<< "x:y"; echo $A; IFS=" "'
44 compare_output "IFS in subshell" '(IFS=:; read A B <<< "x:y"; echo $A $B)'
45 compare_output "IFS reset" 'IFS=:; unset IFS; echo "a b c" | { read A B C; echo $A; }'
46
47 section "6. readonly scope"
48 compare_output "readonly visible in functions" 'readonly SRV=fixed; f() { echo $SRV; }; f'
49 compare_output "readonly visible in subshells" 'readonly SRS=fixed; (echo $SRS)'
50 compare_output "readonly from function persists" 'f() { readonly SRF=in_func; }; f; echo $SRF'
51 compare_output "readonly blocks reassignment" 'readonly SRB=fixed; { SRB=other; } 2>/dev/null; echo $SRB'
52 compare_output "readonly blocks unset" 'readonly SRU=fixed; unset SRU 2>/dev/null; echo $SRU'
53
54 section "7. variable cleanup"
55 compare_output "unset removes var" 'SUV=temp; unset SUV; echo ${SUV:-gone}'
56 compare_output "unset array" 'SUA=(1 2 3); unset SUA; echo ${SUA:-gone}'
57 compare_output "unset function" 'suf() { echo hi; }; unset -f suf; suf 2>/dev/null; echo $?'
58 compare_output "unset in function" 'SUF2=outer; f() { unset SUF2; }; f; echo ${SUF2:-gone}'
59 compare_output "unset exported var" 'export SUE=val; unset SUE; echo ${SUE:-gone}'
60
61 print_summary