#!/bin/bash
#
# Copyright (C) - 2015 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
# Copyright (C) - 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
#
# This library is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; version 2.1 of the License.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
TEST_DESC="UST - Blocking mode"

CURDIR=$(dirname $0)/
TESTDIR=$CURDIR/../../..
SESSION_NAME="blocking"
CHANNEL_NAME="testchan"

TESTAPP_PATH="$TESTDIR/utils/testapp"
TESTAPP_NAME="gen-ust-events"
TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME/$TESTAPP_NAME"
EVENT_NAME="tp:tptest"

NUM_TESTS=49

source $TESTDIR/utils/utils.sh

# MUST set TESTDIR before calling those functions
# Run app on CPU 0 to ensure we only write in a single ring buffer.
function run_app()
{
	taskset 0x00000001 $TESTAPP_BIN $NUM_EVENT
	ok $? "Application done"
}

function test_ust_implicit_no_blocking()
{
	NUM_EVENT=5000000
	diag "UST implicit non-blocking mode (default): will hang if fails"

	start_lttng_sessiond
	# session in no-output mode
	create_lttng_session_no_output $SESSION_NAME
	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
	start_lttng_tracing_ok $SESSION_NAME
	run_app
	stop_lttng_tracing_ok $SESSION_NAME
	destroy_lttng_session_ok $SESSION_NAME
	stop_lttng_sessiond

	ok 0 "Does not hang"
}

function test_ust_implicit_no_blocking_with_channel_blocking()
{
	NUM_EVENT=5000000
	diag "UST implicit non-blocking mode (default) with blocking-timeout=inf channel: will hang if fails"

	start_lttng_sessiond
	# session in no-output mode
	create_lttng_session_no_output $SESSION_NAME
	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=inf"
	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
	start_lttng_tracing_ok $SESSION_NAME
	run_app
	stop_lttng_tracing_ok $SESSION_NAME
	destroy_lttng_session_ok $SESSION_NAME
	stop_lttng_sessiond

	ok 0 "Does not hang"
}

function test_ust_timeout_no_blocking()
{
	NUM_EVENT=12500
	diag "UST 1ms timeout blocking mode: will hang if fails"

	start_lttng_sessiond
	# session in no-output mode
	create_lttng_session_no_output $SESSION_NAME
	# blocking timeout 1ms
	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=1000"
	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
	start_lttng_tracing_ok $SESSION_NAME
	LTTNG_UST_ALLOW_BLOCKING=1 run_app
	stop_lttng_tracing_ok $SESSION_NAME
	destroy_lttng_session_ok $SESSION_NAME
	stop_lttng_sessiond

	ok 0 "Does not hang"
}

function test_ust_snapshot_no_blocking()
{
	NUM_EVENT=5000000
	diag "UST blocking mode: don't block in snapshot mode"

	# Test without the plugin
	start_lttng_sessiond
	create_lttng_session_ok $SESSION_NAME $TRACE_PATH --snapshot
	# blocking timeout 1ms
	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=1000"
	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
	start_lttng_tracing_ok $SESSION_NAME
	LTTNG_UST_ALLOW_BLOCKING=1 run_app
	stop_lttng_tracing_ok $SESSION_NAME
	destroy_lttng_session_ok $SESSION_NAME
	stop_lttng_sessiond

	ok 0 "Does not hang"
}

function test_ust_blocking_no_discard()
{
	NUM_EVENT=5000000
	diag "UST blocking mode: no event discarded"

	# Test without the plugin
	start_lttng_sessiond
	create_lttng_session_ok $SESSION_NAME $TRACE_PATH
	# infinite blocking timeout
	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=inf"
	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
	start_lttng_tracing_ok $SESSION_NAME
	LTTNG_UST_ALLOW_BLOCKING=1 run_app
	stop_lttng_tracing_ok $SESSION_NAME
	destroy_lttng_session_ok $SESSION_NAME
	stop_lttng_sessiond

	nr_events=$(babeltrace $TRACE_PATH 2>/dev/null | wc -l)

	test $nr_events -eq $NUM_EVENT
	ok $? "No event lost with UST blocking mode: found $nr_events expect $NUM_EVENT"
}

plan_tests $NUM_TESTS

print_test_banner "$TEST_DESC"

TESTS=(
	"test_ust_implicit_no_blocking"
	"test_ust_implicit_no_blocking_with_channel_blocking"
	"test_ust_timeout_no_blocking"
	"test_ust_snapshot_no_blocking"
	"test_ust_blocking_no_discard"
)

TEST_COUNT=${#TESTS[@]}
i=0

while [ "$i" -lt "$TEST_COUNT" ]; do

	TRACE_PATH=$(mktemp -d)

	# Execute test
	${TESTS[$i]}

	rm -rf $TRACE_PATH

	let "i++"
done
