#!/bin/bash
#
# Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
#
# SPDX-License-Identifier: GPL-2.0-only
#

TEST_DESC="Perf counters"

CURDIR=$(dirname $0)/
TESTDIR=$CURDIR/..
LTTNG_BIN="lttng"
SESSION_NAME="perf_counters"
NUM_TESTS=21
NR_ITER=1
NR_USEC_WAIT=1
TESTAPP_PATH="$TESTDIR/utils/testapp"
TESTAPP_NAME="gen-ust-events"
TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME/$TESTAPP_NAME"
# Empty if libpfm is installed, "#" otherwise
HAVE_LIBPFM="#"

source $TESTDIR/utils/utils.sh

function enable_ust_lttng_event_per_chan()
{
	sess_name="$1"
	event_name="$2"
	chan_name="$3"

	$TESTDIR/../src/bin/lttng/$LTTNG_BIN enable-event "$event_name" -s $sess_name -c $chan_name -u >/dev/null 2>&1
	ok $? "Enable event $event_name for session $sess_name in channel $chan_name"
}

function have_libpfm()
{
	test -z $HAVE_LIBPFM
	ok $? "Have libpfm installed"
}

function test_ust_raw()
{
	local SESSION_NAME="ust_perf"
	local CHAN_NAME="mychan"
	local EVENT_NAME="tp:tptest"
	local PMU="UNHALTED_REFERENCE_CYCLES"
	local tests_to_skip=9
	local ret
	local TRACE_PATH

	# Find the raw perf id of the event.
	PERFID=$("$CURDIR/find_event" "$PMU")
	ret=$?
	if [ "$ret" -eq "0" ]; then
		pass "Find PMU $PMU"
	elif [ "$ret" -eq "1" ]; then
		skip 0 "PMU event not found." $tests_to_skip
		return
	elif [ "$ret" -eq "2" ]; then
		skip 0 "PMU event not actionable." $tests_to_skip
		return
	else
		fail "find_event returned $ret."
		return
	fi

	TRACE_PATH=$(mktemp --tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")

	create_lttng_session_ok $SESSION_NAME $TRACE_PATH

	enable_ust_lttng_channel_ok $SESSION_NAME $CHAN_NAME

	enable_ust_lttng_event_per_chan $SESSION_NAME $EVENT_NAME $CHAN_NAME

	add_context_ust_ok $SESSION_NAME $CHAN_NAME "perf:thread:raw:${PERFID}:test"

	start_lttng_tracing_ok

	$TESTAPP_BIN -i $NR_ITER -w $NR_USEC_WAIT >/dev/null 2>&1

	stop_lttng_tracing_ok

	destroy_lttng_session_ok $SESSION_NAME

	validate_trace "perf_thread_raw_${PERFID}_test" $TRACE_PATH

	rm -rf $TRACE_PATH
}

function test_kernel_raw()
{
	local SESSION_NAME="kernel_perf"
	local CHAN_NAME="mychan"
	local EVENT_NAME="lttng_test_filter_event"
	local PMU="UNHALTED_REFERENCE_CYCLES"
	local PERFID=""
	local tests_to_skip=9
	local ret
	local TRACE_PATH

	# Find the raw perf id of the event.
	PERFID=$("$CURDIR/find_event" "$PMU")
	ret=$?
	if [ "$ret" -eq "0" ]; then
		pass "Find PMU $PMU"
	elif [ "$ret" -eq "1" ]; then
		skip 0 "PMU event not found." $tests_to_skip
		return
	elif [ "$ret" -eq "2" ]; then
		skip 0 "PMU event not actionable." $tests_to_skip
		return
	else
		fail "find_event returned $ret."
		return
	fi

	TRACE_PATH=$(mktemp --tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")

	create_lttng_session_ok $SESSION_NAME $TRACE_PATH

	lttng_enable_kernel_channel_ok $SESSION_NAME $CHAN_NAME

	enable_kernel_lttng_event_ok $SESSION_NAME $EVENT_NAME $CHAN_NAME

	add_context_kernel_ok $SESSION_NAME $CHAN_NAME "perf:cpu:raw:${PERFID}:test"

	start_lttng_tracing_ok

	echo -n 10 > /proc/lttng-test-filter-event

	stop_lttng_tracing_ok

	destroy_lttng_session_ok $SESSION_NAME

	validate_trace "perf_cpu_raw_${PERFID}_test" $TRACE_PATH

	rm -rf $TRACE_PATH
}

# MUST set TESTDIR before calling those functions
plan_tests $NUM_TESTS

print_test_banner "$TEST_DESC"

start_lttng_sessiond

have_libpfm

test_ust_raw

check_skip_kernel_test 9 ||
{
	modprobe lttng-test
	test_kernel_raw
	modprobe --remove lttng-test
}

stop_lttng_sessiond
