#!/bin/sh
# PCP QA Test No. 273
# Increase testing code coverage in core parts of libpcp
#
# Copyright (c) 2010 Ken McDonell.  All Rights Reserved.
#

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

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

[ -d $PCP_PMDAS_DIR/simple ] || _notrun "simple PMDA directory is not installed"

_cleanup()
{
    _restore_primary_logger
    _restore_auto_restart pmlogger
    $sudo rm -f $tmp.*
    exit $status
}

status=1
$sudo rm -rf $tmp.* $seq.full 
trap "_cleanup" 0 1 2 3 15

_stop_auto_restart pmlogger

_filter()
{
    sed \
	-e 's/0x[0-9a-f][0-9a-f]*/HEX/g' \
    # end
}

# Note - sed at the end is because of non-determinism depending if the
# 	 kernel PMDA is configured to use a dso or other IPC option
#      - pmWhichContext() is called different numbers of times depending
#        on how libpcp was compiled, so strip these lines
#
_filter2()
{
    sed \
	-e '/^pmWhichContext()/d' \
	-e '/pmResult/s/ .* numpmid/ ... numpmid/' \
	-e '/build_dsotab/s/parsing .*/ parsing .../' \
	-e '/^\[[0-9][0-9]*]/d' \
	-e '/^0x[0-9a-f][0-9a-f]* \[[0-9][0-9]*]/d' \
	-e '/^__pmLocalPMDA/d' \
	-e '/^Local Context PMDA Table$/d' \
	-e '/__pmConnectLogger:/s/pid = [0-9][0-9]*/pid = PID/' \
	-e 's/fd=[0-9][0-9]*/fd=N/g' \
	-e '/IPC table fd/s/:.*/: .../' \
	-e '/__pmSendCreds/s/:.*/: .../' \
	-e '/NotifyEndLocalContext: /s/:.*/: .../' \
	-e '/value /s/ [0-9].*/ NUMBER/' \
	-e '/^__pmDataIPC:/d' \
	-e '/^__pmSetDataIPC:/{
N
d
}' \
	-e 's/Permission denied/No permission to perform requested operation/' \
	-e '/__pmConnect(fd=/d' \
    | perl -ne '
	# squash repeated occurrences of the following pattern
	# (as a result of needing to do getaddrinfo list walk)
	if (/^IPC table fd.PDU version.: ...$/) {
	    $saved[1] = $_;
	} elsif (/^__pmSetSocketIPC: fd=N$/) {
	    $saved[0] = $_;
	} else {
	    if ($#saved >= 0) { print $saved[0]; }
	    if ($#saved == 1) { print $saved[1]; }
	    @saved = undef;
	    print;
	}' \
    | sed \
	-e '/^__pmSetSocketIPC:/d' \
	-e '/^NotifyEndLocalContext/d' \
	-e '/^IPC table fd/d' \
    # end
}

_filter3()
{
    sed \
	-e 's/Connection timed out/No route to host/' \
    # end
}

# simple PMDA is using PMDA_INTERFACE_2
#
if [ ! -f $PCP_PMDAS_DIR/simple/pmda_simple.$DSO_SUFFIX ]
then
    ( cd $PCP_PMDAS_DIR/simple; $sudo make; $sudo ./Install </dev/null ) >/dev/null 2>&1
fi

# real QA test starts here
_change_config pmcd on
_change_config pmlogger on
_writable_primary_logger
_service pcp restart >/dev/null 2>&1
_wait_for_pmcd
_wait_for_pmlogger

# help.c
#
$sudo_local_ctx pminfo -t -L sampledso 2>&1
$sudo_local_ctx pminfo -T -L sampledso 2>&1
pminfo -T -a tmparch/foo sample
$sudo_local_ctx pminfo -T -L -n $PCP_PMDAS_DIR/simple/root -K clear -K add,253,simple/pmda_simple.$DSO_SUFFIX,simple_init simple.now 2>&1

# instance.c
#
$sudo_local_ctx pminfo -L -f -Dfetch sampledso.bin 2>&1 | _filter_dumpresult
pminfo -f -Dindom sample.bin 2>&1 | _filter
$sudo pminfo -fL -Dfetch,indom -n $PCP_PMDAS_DIR/simple/root -K clear -K add,253,simple/pmda_simple.$DSO_SUFFIX,simple_init simple 2>&1 \
| _filter_dumpresult | _filter
src/indom sample.bin
src/indom sample.long.one
pmval -s 1 -i "bin-123" sample.bin
$sudo_local_ctx src/torture_indom -L sampledso.colour 2>&1
$sudo_local_ctx src/torture_indom -n $PCP_PMDAS_DIR/simple/root -K clear -K add,253,simple/pmda_simple.$DSO_SUFFIX,simple_init -L simple.now 2>&1

# fetchlocal.c
#
$sudo_local_ctx pminfo -f -L -Dfetch sampledso.bad.unknown 2>&1 | _filter_dumpresult

# spec.c
#
pminfo -f -h localhost:44321 sample.long.hundred
pminfo -f -h localhost:1,44321 sample.long.hundred
pminfo -f -h localhost: sample.long.hundred
pminfo -f -h localhost:44321,1x3 sample.long.hundred
pminfo -f -h localhost:44321@no-host sample.long.hundred 2>&1 | _filter3
pminfo -f -h localhost:44321@no-host:44322 sample.long.hundred 2>&1 | _filter3
pminfo -f -h localhost:44321@ sample.long.hundred

# units.c
#
# Pbyte / hour -> 1F055000
pmstore sample.dynamic.meta.pmdesc.units 0x1F055000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# Ebyte / sec -> 1F063000
pmstore sample.dynamic.meta.pmdesc.units 0x1F063000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# bigger than Ebyte -> 10070000
pmstore sample.dynamic.meta.pmdesc.units 0x10070000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# bigger than Hour -> 01006000
pmstore sample.dynamic.meta.pmdesc.units 0x01006000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# byte^2 -> 20000000
pmstore sample.dynamic.meta.pmdesc.units 0x20000000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# nsec / byte -> F1000000
pmstore sample.dynamic.meta.pmdesc.units 0xF1000000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# / byte^2 -> E0000000
pmstore sample.dynamic.meta.pmdesc.units 0xE0000000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# nsec^3 -> 03000000
pmstore sample.dynamic.meta.pmdesc.units 0x03000000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# / nsec^3 -> 0D000000
pmstore sample.dynamic.meta.pmdesc.units 0x0D000000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# count^2 -> 00200000
pmstore sample.dynamic.meta.pmdesc.units 0x00200000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# / count^2 -> 00E00000
pmstore sample.dynamic.meta.pmdesc.units 0x00E00000 >/dev/null
pminfo -d sample.dynamic.meta.metric
# restore to byte / sec -> 1F003000
pmstore sample.dynamic.meta.pmdesc.units 0x1F003000 >/dev/null

# units.c using grind_cov
#
for type in 0 1 2 3 4 5
do
    # space
    src/grind_conv $type 1024 1:0:0:4:0:0 1:0:0:3:0:0
    src/grind_conv $type 1048576 1:0:0:3:0:0 1:0:0:4:0:0
    # space / time
    src/grind_conv $type 4096 1:-1:0:2:3:0 1:-1:0:3:5:0
    src/grind_conv $type 14400 1:-1:0:3:5:0 1:-1:0:2:3:0
    # space-time / count
    src/grind_conv $type 92160 1:1:-1:1:3:0 1:1:-1:2:4:1
    src/grind_conv $type 15 1:1:-1:2:4:1 1:1:-1:1:3:0
    # time / space
    src/grind_conv $type 1024 -1:1:0:2:3:0 -1:1:0:1:2:0
    src/grind_conv $type 1000 -1:1:0:1:2:0 -1:1:0:2:3:0
done
# and some odd cases and error cases
src/grind_conv -Dvalue 3 4096 1:0:0:5:0:0 1:0:0:6:0:0
src/grind_conv 3 4 1:0:0:6:0:0 1:0:0:5:0:0
src/grind_conv 3 4096 1:0:0:7:0:0 1:0:0:6:0:0
src/grind_conv 3 4096 1:0:0:5:0:0 1:0:0:7:0:0
src/grind_conv 3 3600 0:1:0:0:6:0 0:1:0:0:4:0
src/grind_conv -Dvalue 3 3600 0:1:0:0:4:0 0:1:0:0:6:0 
# dimensions not the same
src/grind_conv 3 0 0:1:0:0:1:0 0:2:0:0:1:0
# cannot convert events
src/grind_conv 8 0 0:1:0:0:1:0 0:1:0:0:1:0

# units.c using src/xval
#
echo
src/xval -D 0x3fffffff 2>&1 \
| sed -e '/pmExtract.*AGGREGATE/{
s/feffff3f/3ffffffe/g
s/ffffff3f/3fffffff/g
s/00000040/40000000/g
}'
src/xval 0x7fffffff
src/xval 0xffffffff
src/xval 0x3fffffffffffffff
src/xval 0x7fffffffffffffff
src/xval 0xffffffffffffffff
src/xval -u 0xffffffffffffffff
echo
src/xval -e

# store.c
#
echo
$sudo_local_ctx src/chknumval -L sampledso.long.write_me sampledso.ulong.write_me sampledso.longlong.write_me >$tmp.out 2>$tmp.err
cat $tmp.err $tmp.out | _filter2

echo
$sudo_local_ctx src/chknumval -Dcontext -L pmcd.control.debug sampledso.long.write_me sample.colour >$tmp.out 2>$tmp.err
cat $tmp.err $tmp.out | _filter2
cat >$tmp.root <<End-of-File
root {
    pmcd
    sample
    sampledso
}
pmcd {
    control
}
pmcd.control {
    debug 2:0:0
}
sample {
    colour 29:0:5
}
sampledso {
    long
}
sampledso.long {
    write_me 30:0:14
}
End-of-File

echo
$sudo_local_ctx src/chknumval -L -n $tmp.root pmcd.control.debug sampledso.long.write_me sample.colour >$tmp.out 2>$tmp.err
cat $tmp.err $tmp.out | _filter2

echo
$sudo_local_ctx src/chknumval -n $PCP_PMDAS_DIR/simple/root -K clear -K add,253,simple/pmda_simple.$DSO_SUFFIX,simple_init -L simple.now simple.now simple.now >$tmp.out 2>$tmp.err
cat $tmp.err $tmp.out | _filter2

# success, all done
status=0
exit
