#!/usr/bin/env ksh
# $Id: xreg.ksh,v 1.23 2013/02/13 00:40:04 ksb Exp $
# Regression test xapply V3.26 (ksb)
# The output should look sane and exit 0, same output on all OS types.
# It takes about 20 seconds to run.					(ksb)
SHELL=`whence sh`
export SHELL
unset PARALLEL

: ${TMPDIR:=/tmp}
while T1=$TMPDIR/xat$$,e$((RANDOM%1000)) ; do
	[ -f $T1 ] || break
done
while T2=$TMPDIR/xat$$,o$((RANDOM%1000)) ; do
	[ -f $T2 ] || break
done
trap 'rm $T1 $T2' EXIT

cat <<\! >$T1
I
II
III
IV
V
!
cat <<\! >$T2
one
two
three
four
five
!

# Clean up any ptbw in our environment
unset ptbw_link ptbw_list ptbw_0 ptbw_1 ptbw_2 ptbw_d

set -e
xapply -V >/dev/null
xapply -h >/dev/null
#   default param processesing
[ _"`xapply -n '1' ''`_" ==  _"`xapply -n '' '1'` _" ]
[ _"`xapply -n '2 3' ''`_" ==  _"`xapply -n '2' '3'` _" ]
[ _"`xapply -n '4 5' ''`_" ==  _"`xapply -n '' '4 5'` _" ]

# -count      number of arguments passed to each command
[ "_A B_" ==  _"`xapply -n -2 '' 'A' 'B'`_" ]
[ "_C D E_" ==  _"`xapply -n -3 '' 'C' 'D' 'E'`_" ]
[ "_F G H I_" ==  _"`xapply -n -4 '' 'F' 'G' 'H' 'I'`_" ]
[ "_x x x " == _"`xapply -a '!' -0 'echo x' 1 2 3 | tr -s ' \n' '  '`" ]
[ "_x x " == _"`xapply -a '!' --2 'echo x' 1 2 3 4| tr -s ' \n' '  '`" ]

# f           arguments are read indirectly one per line rom files
# z           read find-print0 output as input files
[ 2 -eq `find /dev/null /dev/null -print |
	xapply -fn '' - | wc -l` ]
[ 2 -eq `find /dev/null /dev/null -print0 |
	xapply -fzn '' - | wc -l` ]
[ 21 -eq `find /dev/null /dev/null -print |
	xapply -fzn '' - | wc -c` ]

# A           append the tokens as shell parameters
[ "_A 0_" == _"`xapply -A 'echo %1 $1' A`_" ]
# S shell     the shell to run tasks under
for XSH in csh tcsh ksh sh pdksh ash
do
	WSH=`whence $XSH` || continue
	[ "_A 0_" == _"`xapply -A -S$WSH 'echo %1 $1' A`_" ]
done
# and it works for perl too!
if WSH=`whence perl` ; then
	[ "_P0_" == _"`xapply -A -S$WSH 'print "%1",$ARGV[0],"\n";' P`_" ]
fi

# e var=dicer set var to the expansion of dicer for each process
[ "_ExParTay_" == _"`xapply -e E=Ex -e D=Tay 'echo ${E}%1' 'Par$D'`_" ]
[ "_ExParTay Par_" == _"`xapply -e E=Ex -e D=Tay -e A 'echo $E$A$D' 'Par'`_" ]

# dicer 0 param
[ "__" == _"`xapply -n '%0' /dev/null`"_ ]
[ "_%_" == _"`xapply -n '%0%%' /dev/null`"_ ]

# dicer 1 param
[ "_/dev/null_" == _"`xapply -n '%1' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%{1}' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%[1]' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%$' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%{$}' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%[$]' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%*' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%{*}' /dev/null`"_ ]
[ "_/dev/null_" == _"`xapply -n '%[*]' /dev/null`"_ ]
[ "__" == _"`xapply -n '%[1/1]' /dev/null`"_ ]
[ "_dev_" == _"`xapply -n '%[1/2]' /dev/null`_" ]
[ "_null_" == _"`xapply -n '%[1/3]' /dev/null`_" ]
[ "_null_" == _"`xapply -n '%[1/$]' /dev/null`_" ]

# dicer 2 params
[ "_dev_" == _"`xapply -2 -n '%1' 'dev' 'null'`"_ ]
[ "_null_" == _"`xapply -2 -n '%2' 'dev' 'null'`"_ ]
[ "_dev null_" == _"`xapply -2 -n '%*' 'dev' 'null'`_" ]
[ "_dev null_" == _"`xapply -2 -n '' 'dev' 'null'`_" ]
[ "_/dev/null_" == _"`xapply -2 -n '/%1/%2' 'dev' 'null'`_" ]

# dicer double-down
[ "_5271009_" = _`xapply -n "%[1:5,3]" 'ksb:*:11517:2060:KS Braunsdorf,Wizard,5271009:/home/sac1/ksb:/bin/ksh'`_ ]
[ "_9,13:10,22_" = _`xapply -2 -n "%[1,-$,-1]:%[2,-1,-3,-1]" '3,9,13,15' '6,8,10,16,22'`_ ]

# dicer quote ] and blanks, and negative subfields
[ "_k_" = _"`xapply -n '%[1 3]' 'a  b k	s'`_" ]
[ "_s_" = _"`xapply -n '%[1\	2]' 'a  b k	s'`_" ]
[ "_b_" = _"`xapply -n '%[1\ 3]' 'a  b k	s'`_" ]
[ "_[theta_" = _"`xapply -n '%[1\]2,1]' '[5,6][theta,omega]'`_" ]
[ "_]_" = _"`xapply -n '%[1\[-3\6$]' '[5,6][theta,omega]'`_" ]

# %+ shift params to a new cmd, more negative subfields
[ "_5_" = `xapply -2 'echo "_%+_"' "%[1,-$]" "5,6"` ]
[ "_<5,7>_" = `xapply -3 'echo "_%+_"' "<%+>" "%[1,-2]" "5,6,7"` ]
# long standing bug in %u, 2 is the wrong answer here --ksb
[ 0 -eq `echo "echo %u" | xapply -f '%+' /dev/null /dev/null - /dev/null` ]
# another one, sigh.
set _ `(echo a; echo b; echo c) | xapply -nf '%u%1' -`
shift
[ _$1 = _0a ] && [ _$2 = _1b ] && [ _$3 = _2c ]
# long standing bug in %+, we put an extra space after the expansion sometimes
# So this made "abd def", which was wrong.
[ _"abcdef" = _"`xapply -n -2 'a%+ef' 'b%+d'  'c'`" ]

# %f under -f
[ "_${T1} ${T2}_" = _"`xapply -f -2 '%0echo %f1 %f2' $T1 $T2 |tail -1`"_ ]
[ "_${T1} ${T2}_" = _"`xapply -f -2 '%0echo %f*' $T1 $T2 |tail -1`"_ ]
[ "_${T1} ${T2} V five_" = _"`xapply -f -2 'echo %f1 %f2' $T1 $T2 |tail -1`"_ ]
[ "_${T1} ${T2} V five_" = _"`xapply -f -2 'echo %f*' $T1 $T2 |tail -1`"_ ]

# a c         change the escape character
[ "_/dev/null_" == _"`xapply -a @ -2 -n '/@1/@2' 'dev' 'null'`_" ]
[ "_dev null_" == _"`xapply -a~ -2 -n '~*' 'dev' 'null'`_" ]
[ "_dev!null_" == _"`xapply -a! -2 -n '![1]!!!{2}' 'dev' 'null'`_" ]
[ "_dev%null_" == _"`xapply -a! -2 -n '![1]%!{2}' 'dev' 'null'`_" ]

# m           use xclate to manage output streams
# Pjobs       number of tasks to run in parallel
# xclate must be installed from here one
WSH=`whence ksh`
[ "_foofoobarbar_" == _"`xapply -S$WSH -P2 'print "foo\c"; sleep 1; print "%1\c"' bar bar`"_ ]
[ "_foobarfoobar_" == _"`xapply -m -S$WSH -P2 'print "foo\c"; sleep 1; print "%1\c"' bar bar`"_ ]

# u           force the xclate xid to be the expansion of %u, see -N below
set _ `XCLATE_1='-T %x' xapply -m 'expr 7 + %1' 3`
shift
[ 3 -eq $1 ] && [ 10 -eq $2 ]
set _ `XCLATE_1='-T %x' xapply -mu 'expr 7 + %1' 3`
shift
[ 0 -eq $1 ] && [ 10 -eq $2 ]

# i input     change stdin for the child processes
set _ `xapply -f -i $T1 'read L; echo $L %1' $T2 | wc`
shift
[ $1 -eq 5 ] && [ $2 -eq 10 ] && [ $3 -eq 38 ]

# p pad       fill short files with this token
set _ `xapply -2 -f -pthing 'echo %1 %2' $T2 /dev/null | wc`
shift
[ $1 -eq 5 ] && [ $2 -eq 10 ] && [ $3 -eq 54 ]

# ptbw must be installed from the point on
# t tags      list of target resources for %t, start a ptbw
# we can only get the first token (no -J/-P)
set _ `xapply -f -t $T1 'echo %t1 %1' $T2 | wc`
shift
[ $1 -eq 5 ] && [ $2 -eq 10 ] && [ $3 -eq 34 ]

# J tokens    total number of resources required, start a ptbw
# R req       number of resource allocated to each task
# test tableau we build with ptbw
set _ `xapply -fm -J5 -R3 -P5 '%0echo %u %t*' $T1 | sort -n | cut -c 2-`
shift
[ "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14" = "$*" ]
# test that we can get 5 tokens from the T1 file (force -P/-J to be all 5)
set _ `xapply -f -t $T1 -P5 -J5 'echo %t1 %1' $T2 | wc`
shift
[ $1 -eq 5 ] && [ $2 -eq 10 ] && [ $3 -eq 38 ]

# check with an enclosing ptbw (we didn't start)
# -t - and -t /path/to/socket
set _ `ptbw -m -t $T1 -R2 --  sh -c '
	ptbw -A  sh -c "echo \\\$1; sleep 3" _ &
	xapply -AR2 -t - "%0echo \"%t1 %t2\"; sleep 3" "" &
	xapply -AR2 -t $ptbw_1 "%0echo \"%t*\"; sleep 3" "" &
	wait' | tr ' ' '\012' | sort `
shift
[ "I II III IV V" = "$*" ]

# %ft file name for token list
set _ `xapply -t $T1 'echo %ft' BCPL`
shift
[ $1 = "$T1" ] && [ $2 = "BCPL" ]
set _ `xapply -R 2 -J 3 'echo %ft' APL`
shift
[ $1 = "iota" ] && [ $2 = "APL" ]

# %ft through 3 ptbw's (nothing but net)
[ "_${T1}_" = _"`xapply -t $T1 'echo %ft' ''`_" ]
[ "_${T1}_" = _"`ptbw -m -J1 -R4 -t $T1 \
	ptbw -m -J2 -R2 -t - \
	xapply -R2 -t - 'echo %ft' ''`_" ]

# -N else    set zero-pass shell command
set _ `XCLATE_1='-T %x' xapply -m -N "echo zero" 'expr 7 + %1'`
shift
[ 0 -eq $1 ] && [ "00" = "$1" ]  && [ zero -eq $2 ]
set _ `xclate -mr -N '|tr "\000" "\n"' xapply -m -N 'exit 8' exit`
[ _8,00 -eq _$1 ]
set _ `xclate -mr -N '|tr "\000" "\n"' xapply -mu -N 'exit 8' exit`
[ _8,00 -eq _$1 ]

set _ `XCLATE_1='-T %x' xapply -mu -N "echo zero" 'expr 7 + %1'`
shift
[ 0 -eq $1 ] && [ "0" = "$1" ]  && [ zero -eq $2 ]

# check the Mixer
set _ `xapply 'echo %(1,$-~4)' $T1/file
	xapply 'echo %(1,($-~4)($-1))' $T1/file
	xapply 'echo %([1/-1],$-~4)' $T1/file
	xapply 'echo %([1/-1],($-~4)($-1))' $T1/file`
shift
[ _"elif file elif file"  = _"$*" ]

# Check -s, this could be hard as we can't really depend on "time" or "time -p"
if WSH=`whence perl` ; then
	GOTIME=$(perl -e 'print time();')
	xapply -msP2 '[ %u -eq 1 ] && echo hold; sleep %1' 1 9 1 1 1 1 1 1 1 1 >/dev/null
	DELTA=$(perl -e "print time() - $GOTIME;")
	# 9.13 seconds might round to 11 worst case, not 13 w/o -s
	[ $DELTA -le 11 ]
fi

# Test %1 %q1 (double quote protection)
X=`echo abc | tr 'abc' '\n\t '`
[ _'`_\`' = _`xapply -n '%1_%q1' \\\`` ]
[ _'"_\"' = _`xapply -n '%1_%q1' \"` ]
[ _'$_\$' = _`xapply -n '%1_%q1' \$` ]
[ _'\_\\' = _`xapply -n '%1_%q1' \\\\` ]
# Test %1 %Q1 (quote as words for the shell) from xapply 3.63 and up
[ _'`_\`' = _`xapply -n '%1_%Q1' \\\`` ]
[ _'"_\"' = _`xapply -n '%1_%Q1' \"` ]
[ _'$_\$' = _`xapply -n '%1_%Q1' \$` ]
[ _'\_\\' = _`xapply -n '%1_%Q1' \\\\` ]
[ _'~*?[_\~\*\?\[' = _`xapply -n '%1_%Q1' '~*?['` ]
[ _'|&;()_\|\&\;\(\)' = _`xapply -n '%1_%Q1' '|&;()'` ]
[ _'#=\<>_\#\=\\\<\>' = _`xapply -n '%1_%Q1' '#=\<>'` ]
# This was broken in 3.62, fixed in 3.63 --ksb
[ _"NTS_NTSN" = _`xapply -n '%1_%Q1' "$X"| tr ' \n\t\\' 'SNTb'` ]
# Test %1 %W1 (quote as 1 word for the shell) from xapply 3.63 and up
[ _'\_\\' = _`xapply -n '%1_%W1' \\\\` ]
[ _'~*?[_\~\*\?\[' = _`xapply -n '%1_%W1' '~*?['` ]
[ _'|&;()_\|\&\;\(\)' = _`xapply -n '%1_%W1' '|&;()'` ]
[ _'#=\<>_\#\=\\\<\>' = _`xapply -n '%1_%W1' '#=\<>'` ]
[ _"NTS_bNbTbSN" = _`xapply -n '%1_%W1' "$X"| tr ' \n\t\\' 'SNTb'` ]
unset X

# We should't even check features from 3.66 or 4.0 in older versions
XVer=`xapply -V |sed -n -e 's/.*Id: xapply.m,v *\([0-9.]*\).*/\1/p'`
case $XVer in
2.*|3.[0-9]|3.[1-5][0-9]|3.6[0-5])
	exit 0 ;;
3.66|*)
	;;
esac

# xapply < 3.65 changed %[t] to %[ft], which is wrong, now we enforce
# the rule "t must be followed by a number, or other data source".
if [ _/etc/group = _"`xapply -t /etc/group '%1 %[t1]' echo`" ] 2>/dev/null; then
	echo "$PROGNAME: xapply has the %[t] bug." && exit 9
fi
if [ _/etc/group = _"`xapply -t /etc/group '%1 %[t1:1]' echo`" ] 2>/dev/null; then
	echo "$PROGNAME: xapply has the %[t:] bug." && exit 9
fi

# xapply < 3.65 didn't trap '}' replacing a ']'
if [ _one = _"`xapply 'echo %[1}' one 2>&1`" ] ; then
	echo "$PROGNAME: xapply has the %[1} bug." && exit 9
fi

# xapply %p checks, for the whole process control loop
xclate -mrN">$T1" >/dev/null \
    xapply -m '[ %1 -eq 3 ] && kill -USR1 %p && exit 13 || echo %1' 1 1 2 3 5 8
set _ `tr '\000' '\n' <$T1`
if [ '_ 0,1 0,1 0,2 13,3 5 8' != "$*" ] ; then
	echo "$PROGNAME: xapply %p doesn't work" && exit 10
fi

# -P didn't default correctly under mkcmd 8.18 and below
# So we didn't parallel under "-P" like we should have, fixed in mkcmd.
Then=`date +%s`
PARALLEL=5 xapply -P sleep 1 1 1 1 1
Now=`date +%s`
if expr 3 \< $Now - $Then >/dev/null ; then
	echo "$PROGNAME: upgrade mkcmd to at least 8.19 Patch1"
fi

# check 3.66+ expands: %~*, %~1, %[{1}92], %[t], %ft, %tf, %fp, %[ft]
echo "OK" >$T2
[ _"null dev"_ = _"`xapply -2 -n '%~*' 'dev' 'null'`_" ] || exit 11
[ _"last" = _"`xapply -n -3 '%~1' first middle last`" ] || exit 11
\
	[ _"67" = _"`xapply -n '%[{1}92]' 5967`" ] || exit 11
[ _"OK" = _"`xapply -t $T2 '%* %[t*]' echo`" ] || exit 11
[ _"group" = _"`xapply -n -t /etc/group '%0%f[t/$]' ''`" ] || exit 11
[ _"group" = _"`xapply -n -t /etc/group '%0%[ft/$]' ''`" ] || exit 11
[ _"/etc/group" = _"`xapply -t /etc/group '%1 %[ft]' echo`" ] || exit 11
[ _"/etc/group" = _"`xapply -t /etc/group '%1 %[tf]' echo`" ] || exit 11
[ _"group" = _"`xapply -t /etc/group '%1 %t[f/$]' echo`" ] || exit 11
[ _"ylppax happy" = _"`xapply -n '%f(p,$-1)' happy`" ] || exit 11
[ _"ylppax happy" = _"`xapply -n '%(fp,$-1)' happy`" ] || exit 11
[ _"atoi happy" = _"`xapply -n '%f(u,$-1)' happy`" ] || exit 11
[ _"atoi happy" = _"`xapply -n '%f(u,$-1)' happy`" ] || exit 11
[ _"`xapply -n '%u' Y`"    = _"`xapply -n '%u' Y`" ] || exit 12
[ _"`xapply -n '%f{u}' K`" = _"`xapply -n '%fu' K`" ] || exit 12
if Gtw=`whence gtfw` ; then
$Gtw -m sh -c \
    '[ _"`xapply -gn \"%f{u}\" J`" = _"`xapply -gn \"%fu\" J`" ]' || exit 12
fi
[ _"`xapply -n '%t{u}' L`" = _"`xapply -n '%tu' L`" ] || exit 12
[ _"`xapply 'echo %p' M |sed -e 's/[0-9]*/pid/'`"    = _"`xapply 'echo %p' M |sed -e 's/[0-9]*/pid/'`" ] || exit 12
[ _"`xapply 'echo %f{p}' N`" = _"`xapply 'echo %fp' N`" ] || exit 12
[ _"`xapply 'echo %t{p}' O`" = _"`xapply 'echo %tp' O`" ] || exit 12

# check %t+, for simple cases
echo "uname" >$T1
[ _"uname -a" = _"`xapply -n -t$T1 -R1 '%t+' -a 2>/dev/null`" ] || exit 24
echo "uname %(1,\$-1)" >$T2
[ _"uname -a" = _"`xapply -n -t$T2 -R1 '%t+' a- 2>/dev/null`" ] || exit 24

# check 3.73 -F option and %c %fc %tc markup
[ _"#!/.$SHELL" = _"`SHELL=/.$SHELL xapply 'echo %Wtc%0' 0`" ] || exit 26

# Only if we have env -S test that, else use -F literally
if env -S "echo true" >/dev/null 2>/dev/null ; then
	cat >$T1 <<\!
#!/usr/bin/env -S xapply -F
echo  gzip %*
!
	cat >$T2 <<\!
#!/usr/bin/env -S xapply -F
# mark this
grep %W1 %fc
!
	chmod +x $T1 $T2
	[ _"gzip aa gzip bb " = _"`$T1 aa bb | tr '\n ' '  '`" ] || exit 25
	[ _"gzip aa bb" = _"`$T1 -2 aa bb`" ] || exit 25
	[ _"echo  gzip aa bb" = _"`$T1 -n -2 aa bb`" ] || exit 25
	[ _"#!/usr/bin/env -S xapply -F" = _"`$T2 -N "echo %Wtc%0"`" ] || exit 26
	[ _"# mark this" = _"`$T2 this`" ] || exit 26
	[ _"grep %W1 %fc" = _"`$T2 grep`" ] || exit 26
else
	cat >$T1 <<\!
echo  gzip %*
!
	cat >$T2 <<\!
#!/bin/sh
# mark this
grep %W1 %fc
!
	chmod -x $T1 $T2
	[ _"gzip aa gzip bb " = _"`xapply -F $T1 aa bb | tr '\n ' '  '`" ] || exit 25
	[ _"gzip aa bb" = _"`xapply -F $T1 -2 aa bb`" ] || exit 25
	[ _"echo  gzip aa bb" = _"`xapply -F $T1 -n -2 aa bb`" ] || exit 25
	[ _"#!/bin/sh" = _"`xapply -F $T2 -N "echo %Wtc%0"`" ] || exit 26
	[ _"# mark this" = _"`xapply -F $T2 this`" ] || exit 26
	[ _"grep %W1 %fc" = _"`xapply -F $T2 grep`" ] || exit 26
fi

exit 0
