#!/bin/bash
#
# SPDX-FileCopyrightText: 2013 Christian Babeux <christian.babeux@efficios.com>
# SPDX-FileCopyrightText: 2014 Julien Desfossez <jdesfossez@efficios.com>
#
# SPDX-License-Identifier: GPL-2.0-only

TEST_DESC="UST tracer - Perf counters"

CURDIR=$(dirname "$0")/
TESTDIR=$CURDIR/../..

session_name="perf_counters"

EVENT_NAME="tp:tptest"

UST_NUM_TESTS=16
ROOT_NUM_TESTS=9
NUM_TESTS=$((UST_NUM_TESTS + ROOT_NUM_TESTS))

NR_ITER=1
NR_USEC_WAIT=1

TESTAPP_PATH="$TESTDIR/utils/testapp"
TESTAPP_NAME="gen-ust-events"
TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME"

# shellcheck source-path=SCRIPTDIR/../..
source "$TESTDIR/utils/utils.sh"

function add_context_ust_skip_ok()
{
	local session_name=$1
	local channel_name=$2
	local context_name=$3
	local skip_num=$4

	local ret

	_run_lttng_cmd "$(lttng_client_log_file)" "$(lttng_client_err_file)" \
		add-context -u -s "$session_name" -c "$channel_name" \
		-t "$context_name"
	ret=$?

	if [ "$ret" == "4" ]; then
		skip 0 "Current UST lib doesn't implement '$context_name' context" "$skip_num"
	else
		ok $ret "Add context command for type: $context_name"
	fi

	return $ret
}

# Only test parsing of the enabling by raw ID
function test_perf_event_parsing_raw()
{
	local session_name="ust_event_basic"
	local chan_name="mychan"

	local trace_path

	trace_path=$(mktemp -d -t "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_ok $session_name $EVENT_NAME $chan_name

	add_context_ust_skip_ok $session_name $chan_name "perf:thread:raw:r0110:test" 1
	add_context_ust_fail $session_name $chan_name "perf:thread:raw:rZZZ:test"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw:b0110:test"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw:r0110:"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw:r0110::"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw:r:test"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw:r::"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw::"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw"
	add_context_ust_fail $session_name $chan_name "perf:thread:raw:r0110:test:wrong"

	destroy_lttng_session_ok $session_name

	rm -rf "$trace_path"
}

function test_perf_event_basic()
{
	local session_name="ust_event_basic"
	local chan_name="mychan"

	local ret
	local trace_path
	local file_testapp_output

	trace_path=$(mktemp -d -t "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
	file_testapp_output=$(mktemp -u -t "tmp.${FUNCNAME[0]}_testapp_output.XXXXXX")

	create_lttng_session_ok $session_name "$trace_path"

	enable_ust_lttng_channel_ok $session_name $chan_name

	enable_ust_lttng_event_ok $session_name $EVENT_NAME $chan_name

	add_context_ust_skip_ok $session_name $chan_name "perf:thread:page-fault" 4
	ret=$?

	if [ "$ret" != "4" ]; then
		start_lttng_tracing_ok

		run_testapp_ok "$file_testapp_output" "$TESTAPP_BIN" -i "$NR_ITER" -w "$NR_USEC_WAIT"

		stop_lttng_tracing_ok

		validate_trace "perf_thread_page_fault" "$trace_path"
	fi

	destroy_lttng_session_ok $session_name

	rm -rf "$trace_path"
	rm -f "$file_testapp_output"
}

# MUST set TESTDIR before calling those functions
plan_tests $NUM_TESTS

print_test_banner "$TEST_DESC"

bail_out_if_no_babeltrace

start_lttng_sessiond

test_perf_event_parsing_raw

check_skip_kernel_test $ROOT_NUM_TESTS "Skipping UST perf tests." ||
{
	test_perf_event_basic
}

stop_lttng_sessiond
