#!/bin/sh
#
# Make a new PCP QA test
#
# Copyright (c) 1997-2002 Silicon Graphics, Inc.  All Rights Reserved.
#
# Usage: new [-n|-r|-s|-v] [base-seq-no group ...]
#
# base-seq-no defaults to some random place in the range $min-$max
#

# generic initialization
. ./common.rc

min=1600
max=1899
max_probes=200

_usage()
{
    echo >&2 "Usage: new [options] [starting-seq-no [group ...]]"
    echo >&2
    echo >&2 "Options:"
    echo >&2 "-n   show-me, change nothing"
    echo >&2 "-r   reserve (and skeletal test added)"
    echo >&2 "-s   pick smallest unallocated test number"
    echo >&2 "     [default and preferred is to choose at random]"
    echo >&2 "-v   verbose"
    echo >&2
    echo >&2 "starting-seq-no changes where search starts, but maybe - to ignore"
    echo >&2 "if group(s) specified on the command line"

    exit 1
}

showme=false
reserve=false
verbose=false
smallest=false
random=true
while getopts 'nrsv?' p
do
    case "$p"
    in
	n)	showme=true
		;;
	r)	reserve=true
		;;
	s)	smallest=true
		random=false
		;;
	v)	verbose=true
		;;
	?)	echo "bad arg: $p"; _usage
		# NOTREACHED
    esac
done
shift `expr $OPTIND - 1`

tmp=/tmp/$$
trap "rm -f $tmp.*; exit" 0 1 2 3 15

_cleanup()
{
    :
}

if [ "$USER" = "pcpqa" ]
then
    if [ ! -z "$REMOTEUSER" -a "$REMOTEUSER" != UNKNOWN ]
    then
	USER=$REMOTEUSER
    else
	echo "Error: user \"pcpqa\" cannot create tests ... who are you?"
	$PCP_ECHO_PROG $PCP_ECHO_N "Enter login: ""$PCP_ECHO_C"
	read USER
	if [ ! -z "$USER" ]
	then
	    grep "^$USER:" /etc/passwd >/dev/null || USER=''
	fi
	if [ -z "$USER" ]
	then
	    echo "If you're not going to be serious, then I won't play"
	    exit 1
	fi
    fi
fi

if [ ! -f group ]
then
    echo "Creating the group index ..."
    cat <<'End-of-File' >group
## QA groups control
##
## define groups
##
## Do not start group name with a digit, expect alphabetic
##
## Last comment starting with a single # before a group name is the
## one-line summary that "new" will report when asked to list groups
##
## Comments starting with a ## (or #<anything_other_than_whitesspace>
## are ignored for the purposes of one-line summaries.

# catch-all
other

## test-group association ... one line per test
## add :retired or :reserved as a tag immediately after the test number
## to keep the test number allocated, but prevent the test from being run

## ... use sort -n from here on down to tidy up this mess
##
End-of-File
fi

if [ ! -w group ]
then
    echo "Error: cannot write index file \"group\""
    _cleanup
    exit 1
fi

if [ -f GNUmakefile.install ]
then
    # running QA in the tree
    ${MAKE:-make} -f GNUmakefile.install >$tmp.out 2>&1
else
    ${MAKE:-make} >$tmp.out 2>&1
fi
if [ $? -ne 0 ]
then
    cat $tmp.out
    echo "Warning: ${MAKE:-make} failed -- some tests may be missing"
fi

try=""
if [ $# -gt 0 ]
then
    if [ x"$1" != x- ]
    then
	try=`printf "%03d\n" $1`
	random=false
    fi
    shift
fi
if [ -z "$try" ]
then
    if $smallest
    then
	# as of 15 Jun 2018, we're all full up to 650 and a bit
	#
	try=650
    else
	# random in the range $min-$max based on user name convered from alpha
	# to numeric, prefixed by current clock seconds
	#
	seed="`date +%S``echo $USER | tr 'a-z' '0-90-90-9'`"
	try=`awk 'BEGIN { srand('"$seed"'); printf "%03d\n",int('$min'+rand()*('$max'-'$min')) }' </dev/null`
    fi
fi

# first $try, then keep randomly probing the min-max space
#
$verbose && echo >&2 "Info: start probing at $try"
probe=0
while [ $probe -lt $max_probes ]
do
    if grep "^$try[ :]" <group >/dev/null
    then
	# already allocated ... try again
	#
	seed=$try
	if $random
	then
	    try=`awk 'BEGIN { srand('"$seed"'); printf "%03d\n",int('$min'+rand()*('$max'-'$min')) }' </dev/null`
	    probe=`expr $probe + 1`
	else
	    try=`expr $try + 1`
	    try=`printf "%03d\n" $try`
	fi
	$verbose && echo >&2 "Info: try $try"
    else
	id=$try
	break
    fi
done

if [ $probe -eq $max_probes ]
then
    echo >&2 "Error: after $max_probes attempts, no unassigned tests in the range $min ... $max.  Time to increase \$max"
    exit 1
fi

if $showme
then
    echo $id
    exit
fi

echo "Allocated test number $id"

if [ -f $id ]
then
    echo >&2 "Error: test $id already exists, but not in group file!"
    _cleanup
    exit
fi

cat <<End-of-File >$id
#!/bin/sh
# PCP QA Test No. $id
End-of-File
if $reserve
then
    echo "# Test reserved by $LOGNAME on `date`" >>$id
fi
cat <<End-of-File >>$id
# [what am I here for?]
#
# Copyright (c) `date +%Y` [who are you?].  All Rights Reserved.
#

if [ \$# -eq 0 ]
then
    seq=\`basename \$0\`
    echo "QA output created by \$seq"
else
    # use \$seq from caller, unless not set
    [ -n "\$seq" ] || seq=\`basename \$0\`
    echo "QA output created by \`basename \$0\` \$*"
fi

# get standard environment, filters and checks
. ./common.product
. ./common.filter
. ./common.check

do_valgrind=false
if [ "\$1" = "--valgrind" ]
then
    _check_valgrind
    do_valgrind=true
fi

# test for-some-thing || _notrun No support for some-thing

_cleanup()
{
    cd \$here
    \$sudo rm -rf \$tmp \$tmp.*
}

status=0	# success is the default!
\$sudo rm -rf \$tmp \$tmp.* \$seq.full
trap "_cleanup; exit \\\$status" 0 1 2 3 15

_filter()
{
    sed \\
	-e 's/<something>/<else>/' \\
    # end
}

# real QA test starts here

if \$do_valgrind
then
    _run_valgrind ...your test goes here...
else
    ...your test goes here... 2>&1
fi \\
| _filter

# if really bad error
status=1
exit

# optional stuff if your test has verbose output to help resolve problems
#echo
#echo "If failure, check \$seq.full"

# success, all done
exit
End-of-File
chmod 755 $id

if $reserve
then
    echo "Creating skeletal $id script"
    tag=":reserved"
else
    $PCP_ECHO_PROG $PCP_ECHO_N "Creating skeletal $id script for you to edit ...""$PCP_ECHO_C"
    sleep 2		# latency to read messages to this point, before vi(1)
    echo ""
    ${EDITOR-vi} $id
    tag=""
fi

if [ $# -eq 0 ]
then
    while true
    do
	$PCP_ECHO_PROG $PCP_ECHO_N "Add to group(s) [other] (? for list): ""$PCP_ECHO_C"
	read ans
	[ -z "$ans" ] && ans=other
	if [ "X$ans" = "X?" ]
	then
	    $PCP_AWK_PROG <group '
BEGIN		{ text = "# ???" }
/^[a-zA-Z]/	{ printf "%-16.16s %s\n",$1,text; text = "# ???"; next }
NF < 2		{ next }
$1 == "#"	{ text = $0 }' \
	    | LC_COLLATE=POSIX sort
	else
	    break
	fi
    done
    $PCP_ECHO_PROG $PCP_ECHO_N "Runs on QA machine alone? (local pmcd, local pmlogger, no ssh, ...) [y] ""$PCP_ECHO_C"
    read _ans
    if [ -z "$_ans" -o "$_ans" = "y" ]
    then
	ans="$ans local"
    else
	ans="$ans remote"
    fi
else
    # expert mode, groups are on the command line
    #
    for g in $*
    do
	if sed -e 's/$/ /' <group | grep "^$g[ 	]" >/dev/null
	then
	    :
	else
	    echo "Warning: group \"$g\" not defined in ./group"
	fi
    done
    ans="$*"
fi

echo "Adding $id to group index"
echo "$id$tag $ans" >>group

# sort the tests numerically
#
$PCP_AWK_PROG <group '
BEGIN				{ state = "head" }
state == "head" && /^[0-9]/	{ state = "list" }
				{ print >"'$tmp'." state }'
sort -n $tmp.list >>$tmp.head
cp $tmp.head group

# make a $id.out placeholder if not already done
#
if [ ! -f $id.out ]
then
    echo "Creating skeletal output, $id.out"
    echo "QA output created by $id" >$id.out
    echo "[skeleton from qa/new, replace me]" >>$id.out
fi

# and finally, don't forget the git work ...
#
git add $id $id.out

exit 0
