#!/bin/sh
# PCP QA Test No. 1662
# Test pmproxy libpcp_web discovery file descriptor and
# memory leaks (valgrind variant, originally 1661-based
# but now quite different to work with valgrind).
#
# Copyright (c) 2019,2022 Red Hat.  All Rights Reserved.
#

seq=`basename $0`
echo "QA output created by $seq"

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

_check_valgrind
_check_series
_check_key_server_version_offline

_cleanup()
{
    test -n "$pmlogger_pid" -a -d "/proc/$pmlogger_pid" \
	&& $signal -TERM $pmlogger_pid
    test -n "$pmlogger2_pid" -a -d "/proc/$pmlogger2_pid" \
	&& $signal -TERM $pmlogger2_pid
    test -n "$key_server_port" && $keys_cli -p $key_server_port shutdown
    cd $here
    $sudo rm -rf $tmp $tmp.*
}

_filter()
{
    echo "=== valgrind output" >>$seq_full
    tee -a $seq_full \
    | sed \
	-e "s,$PCP_BINADM_DIR,PCP_BINADM_DIR,g" \
	-e "s,-c $tmp.conf ,-c CONFFILE ,g" \
	-e "s,-U $username ,-U USERNAME ,g" \
	-e "s,-l $tmp.pmproxy,-l LOGFILE,g" \
	-e "s,-r $key_server_port,-r KEYSPORT,g" \
	-e "s,-p $PROXYPORT,-p PROXYPORT,g" \
	-e "s,-s $PROXYSOCK,-s PROXYSOCK,g" \
    | _filter_valgrind_possibly
}

status=1	# failure is the default!
signal=$PCP_BINADM_DIR/pmsignal
username=`id -un`
dir="$tmp.qa$seq"
trap "_cleanup; exit \$status" 0 1 2 3 15
src/time_stamp $tmp.stamp begin >>$seq_full

# real QA test starts here
mkdir $dir

#
# Test plan is as follows:
# - create a local key server to catch discovered data
# - create a directory to house freshly created archives
# - run pmlogger in frequent-writes+volume-switching mode,
#   background-writing archives below new local directory
# - run valgrind+pmproxy for a while, see what it uncovers
# 

key_server_port=`_find_free_port`
src/time_stamp $tmp.stamp 'key server start' >>$seq_full
$key_server --port $key_server_port --save "" > $tmp.keys 2>&1 &
_check_key_server_ping $key_server_port
src/time_stamp $tmp.stamp 'key server active' >>$seq_full

cat > $tmp.sample << EOF2
log advisory on default { sample }
EOF2
src/time_stamp $tmp.stamp 'pmlogger start' >>$seq_full
pmlogger -t 2.5sec -v 5k -c config.default -T9sec -l$tmp.pmlogger $dir/test &
pmlogger_pid=$?
( sleep 3 && pmlogger -t 1.5sec -v 4k -c $tmp.sample -T4sec -l$tmp.pmlogger2 $dir/test2 ) 2>/dev/null &
pmlogger2_pid=$?
src/time_stamp $tmp.stamp 'pmlogger active' >>$seq_full

PROXYPORT=`_find_free_port`
PROXYSOCK=$tmp.pmproxy.sock
cat > $tmp.conf << EOF
[keys]
enabled = true
[pmseries]
enabled = true
[pmsearch]
enabled = false
[discover]
enabled = true
path = $dir
EOF
src/time_stamp $tmp.stamp 'pmproxy start' >>$seq_full
grind_extra="--track-origins=yes --read-var-info=yes --read-inline-info=yes"
# skip valgrind errors in upstream non-PCP code, like hiredis ...
# (seen on vm11 Debian 10.13)
# ... same suppressions as for qa/1290
#
cat <<'End-of-File' >$tmp.suppress
{
   sds.c: % operator: v seems well defined, so maybe valgrind botch
   Memcheck:Cond
   fun:__umoddi3
   fun:sdsll2str
   fun:sdscatfmt
   fun:keys_series_label
   fun:keys_series_labelset
   fun:keys_series_metadata
   fun:keys_series_metric
   ...
}
{
   sds.c: / operator: ditto
   Memcheck:Cond
   fun:__udivdi3
   fun:sdsll2str
   fun:sdscatfmt
   fun:keys_series_label
   fun:keys_series_labelset
   fun:keys_series_metadata
   fun:keys_series_metric
   ...
}
{
   sds.c: conditional: value and v seems well defined, so maybe valgrind botch
   Memcheck:Cond
   fun:sdsll2str
   fun:sdscatfmt
   fun:keys_series_label
   fun:keys_series_labelset
   fun:keys_series_metadata
   fun:keys_series_metric
   ...
}
{
   net.c: uninitialized buffer on async i/o path
   Memcheck:Param
   socketcall.send(msg)
   fun:send
   fun:redisNetWrite
   fun:redisBufferWrite
   fun:redisAsyncWrite
   fun:redisAsyncHandleWrite
   fun:redisLibuvPoll
   ...
}
End-of-File
grind_extra="$grind_extra --suppressions=$tmp.suppress"
_run_valgrind $PCP_BINADM_DIR/pmproxy -Ddev0,discovery \
	-f -t -A -c $tmp.conf -U $username -T 10sec -l $tmp.pmproxy \
	-r $key_server_port -p $PROXYPORT -s $PROXYSOCK \
	| _filter
src/time_stamp $tmp.stamp 'pmproxy exited' >>$seq_full

echo "=== key server log ===" >> $seq_full
cat $tmp.keys >> $seq_full
echo "=== pmlogger log ===" >> $seq_full
cat $tmp.pmlogger >> $seq_full
echo "=== pmlogger2 log ===" >> $seq_full
cat $tmp.pmlogger2 >> $seq_full
echo "=== pmproxy log ===" >> $seq_full
cat $tmp.pmproxy >> $seq_full

# success, all done
status=0
exit
