#! /usr/bin/env modernish
#! use safe -k
#! use sys/cmd/harden
#! use var/local
#! use var/stack/extra/clearstack
#! use var/stack/extra/stacksize

# This tests LOCAL blocks: local variables and shell options within
# arbitrary code blocks (var/local module).
# See README.md under "Modules" -> "use var/local" for more info.

harden -p -f number_lines pr -t -n
harden -p printf

putln '-----Test 1-----'
putln 'Globbing off:'
put *
LOCAL +o noglob; BEGIN
	putln '' 'Globbing on:'
	put *
	return 2
END
putln '' "(Exit status of local block should be 2, was $?)"
putln 'Globbing off again:'
put *

putln '' '' '-----Test 2------'
X=12 Y=13
putln "     Global1:${CCt}X=$X${CCt}Y=$Y"
LOCAL X=2 Y=4 splitthis='this string should not be subject to field splitting.'; BEGIN
	putln "      Local1:${CCt}X=$X${CCt}Y=$Y"
	LOCAL X=hi Y=there IFS splitthis='look ma, i can do local field splitting!'; BEGIN
		putln "NestedLocal1:${CCt}X=$X${CCt}Y=$Y"
		X=13 Y=37
		putln "NestedLocal2:${CCt}X=$X${CCt}Y=$Y"
		putln $splitthis | number_lines
	END
	putln "      Local2:${CCt}X=$X${CCt}Y=$Y"
	X=123 Y=456
	putln "      Local3:${CCt}X=$X${CCt}Y=$Y"
	putln $splitthis | number_lines
END
putln "     Global2:${CCt}X=$X${CCt}Y=$Y"

putln '' '------Test 3------' '(If you see anything other than the files in your PWD below, there is an undiscovered bug!)'
# (Due to a bug, mksh [up to R54 2016/11/11] throws a syntax error if you use $( ) instead of ` `.
# Not that this really matters. In real-world programs you would not need to do this.)
result=`LOCAL IFS= +o noglob; BEGIN printf '[%s] ' * | fold -s; END`
putln $result

putln '' '------Test 3a------'
putln one two three four | LOCAL X IFS=$CCn; BEGIN while read X; do put "[$X] "; done; echo; END

putln '' '------Test 4------' 'Testing protection against stack corruption.'
LOCAL testvar='stack corruption protection test: '; BEGIN
	put $testvar
	push var3
	push var3 var2
	push var3 var2 var1
	pop var3 var2 testvar var1   # this should fail due to a key mismatch
	let "$? == 2" || return 1
	stacksize --silent var3
	let "REPLY == 3" || return 1
	stacksize --silent var2
	let "REPLY == 2" || return 1
	stacksize --silent var1
	let "REPLY == 1" || return 1
	clearstack var1 var2 var3
END && putln "ok" || putln "FAILED"

putln '' '------Test 5------' 'This test should fail with: "stack corrupted (failed to pop globals)".'
LOCAL testvar=$CCv'stack corruption test test...'$CCn; BEGIN
	putln $testvar
	push testvar
	# Failing to restore a local variable's stack within the block will stop 'LOCAL'
	# from restoring global settings due to a key mismatch, killing the program.
END
putln 'Bad! We should never get here.'
exit 128
