--- /dev/null
+#!/bin/bash
+#
+# Copyright (C) - 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficiso.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="Notification"
+
+CURDIR=$(dirname $0)/
+TESTDIR=$CURDIR/../../../
+
+# This is needed since the testpoint creates a pipe with the consumerd domain
+# suffixed
+TESTPOINT_BASE_PATH=$(readlink -f "$CURDIR/lttng.t_p_n")
+TESTPOINT_PIPE_PATH=$(mktemp -u "${TESTPOINT_BASE_PATH}.XXXXXX")
+TESTPOIT_ARGS="CONSUMER_PAUSE_PIPE_PATH=${TESTPOINT_PIPE_PATH} LTTNG_TESTPOINT_ENABLE=1"
+TESTPOINT=$(readlink -f ${CURDIR}/.libs/libpause_consumer.so)
+
+TESTAPP_PATH="$TESTDIR/utils/testapp"
+TESTAPP_NAME="gen-ust-events"
+TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME/$TESTAPP_NAME"
+
+NR_ITER=-1
+NR_USEC_WAIT=5
+
+SESSION_NAME="my_session"
+UST_CHANNEL_NAME="my_ust_channel"
+EVENT_NAME="tp:tptest"
+
+NR_NOTIFICATION_EXPECTED=5
+NR_CLIENT_APP=50
+
+TRACE_PATH=$(mktemp -d)
+
+DIR=$(readlink -f $TESTDIR)
+
+NUM_TESTS=46
+
+source $TESTDIR/utils/utils.sh
+
+consumerd_pipe=()
+file_sync_after_first_event=$(mktemp -u)
+
+# MUST set TESTDIR before calling those functions
+plan_tests $NUM_TESTS
+
+print_test_banner "$TEST_DESC"
+
+app_pids=()
+function start_client {
+ local pid=-1
+ local output_file=$1
+ local session_name=$2
+ local channel_name=$3
+ local domain_type=$4
+ local buffer_usage_type=$5
+ local buffer_usage_threshold_type=$6
+ local buffer_usage_threshold_value=$7
+ local nr_expected_notification=$8
+
+ ${CURDIR}/base_client ${session_name} ${channel_name} ${domain_type} ${buffer_usage_type} ${buffer_usage_threshold_type} ${buffer_usage_threshold_value} ${nr_expected_notification} > ${output_file} &
+ pid=$!
+
+ app_pids+=("$pid")
+}
+
+function wait_for_message ()
+{
+ local file_pattern=$1
+ local message=$2
+
+ for file in $CURDIR/${file_pattern}*; do
+ while(true); do
+ # Check for "error" message
+ grep -q "error:" ${file}
+ app_error=$?
+ if [ $app_error -eq "0" ] ; then
+ # An error occurred
+ fail "Waiting message: error logged see file content: ${message}, ${file}"
+ return 1
+ fi
+
+ grep -q "${message}" ${file}
+ if [[ "$?" -ne "0" ]]; then
+ # Lookup failed restart loop
+ diag "Lookup failed sleep and retry grep for: ${message}, ${file}"
+ sleep 0.25
+ continue
+ fi
+ break
+ done
+ done
+ pass "Message received: ${message}"
+ return 0
+}
+
+function print_errors ()
+{
+ local file_pattern=$1
+
+ for file in $CURDIR/${file_pattern}*; do
+ # Check for "error" message
+ error_message=$(grep "error:" ${file})
+ if [[ "${error_message}" -ne "" ]]; then
+ diag "Errors for application ${file}:"
+ diag "${error_message}"
+ fi
+ done
+}
+
+function comm_consumerd ()
+{
+ local message=$1
+ local pipe=$2
+ echo -ne "${message}" > "${pipe}"
+ return $?
+}
+
+function stop_consumerd ()
+{
+ local pipe=$1
+ comm_consumerd "1" "$pipe"
+ ok $? "Stopping consumption consumerd"
+}
+
+function resume_consumerd ()
+{
+ local pipe=$1
+ comm_consumerd "\0" "$pipe"
+ ok $? "Resuming consumerd"
+}
+
+function test_multi_app ()
+{
+ local app_pids=()
+ local low_output_file_pattern="low_app_output_file_"
+ local high_output_file_pattern="high_app_output_file_"
+
+ # Cleanup
+ rm ${CURDIR}/${low_output_file_pattern}* 2> /dev/null
+ rm ${CURDIR}/${high_output_file_pattern}* 2> /dev/null
+
+ # Setup
+ LTTNG_SESSIOND_ENV_VARS="LTTNG_TESTPOINT_ENABLE=1 CONSUMER_PAUSE_PIPE_PATH=${TESTPOINT_PIPE_PATH} LD_PRELOAD=${TESTPOINT}"
+ start_lttng_sessiond
+
+ # Start app in infinite loop
+ $TESTAPP_BIN $NR_ITER $NR_USEC_WAIT $file_sync_after_first_event &
+ app_pid=$!
+ # Pin to CPU zero to force specific sub buffer usage
+ taskset -p -c 0 $app_pid > /dev/null 2>&1
+
+ # Wait for sync with app
+ while [ ! -f "${file_sync_after_first_event}" ]; do
+ sleep 0.5
+ done
+ rm ${file_sync_after_first_event}
+
+ create_lttng_session_ok $SESSION_NAME $TRACE_PATH
+ enable_ust_lttng_channel_ok $SESSION_NAME $UST_CHANNEL_NAME --subbuf-size=4096
+ enable_ust_lttng_event_ok $SESSION_NAME $EVENT_NAME $UST_CHANNEL_NAME
+
+ # Fetch consumerd testpoint pipe information
+ # This is needed since the testpoint create a pipe with the consumer type suffixed
+ for f in "$TESTPOINT_BASE_PATH"*; do
+ consumerd_pipe+=("$f")
+ done
+
+ for (( i = 0; i < $NR_CLIENT_APP; i++ )); do
+ low_app_output_file=$CURDIR/${low_output_file_pattern}${i}
+ high_app_output_file=$CURDIR/${high_output_file_pattern}${i}
+ start_client $low_app_output_file $SESSION_NAME $UST_CHANNEL_NAME LTTNG_DOMAIN_UST LOW RATIO 0.0 $NR_NOTIFICATION_EXPECTED
+ start_client $high_app_output_file $SESSION_NAME $UST_CHANNEL_NAME LTTNG_DOMAIN_UST HIGH RATIO 0.420 $NR_NOTIFICATION_EXPECTED
+ done
+
+ wait_for_message "${low_output_file_pattern}" "sync: ready"
+ wait_for_message "${high_output_file_pattern}" "sync: ready"
+
+ # Test notification reception
+ for (( i = 0; i < $NR_NOTIFICATION_EXPECTED; i++ )); do
+
+ # Stop consumerd consumption to force high notification
+ start_lttng_tracing_ok $SESSION_NAME
+ for pipe in "${consumerd_pipe[@]}"; do
+ stop_consumerd "${pipe}"
+ done
+
+ wait_for_message "${high_output_file_pattern}" "notification: high $i"
+
+ # Resume consumerd
+ for pipe in "${consumerd_pipe[@]}"; do
+ resume_consumerd "${pipe}"
+ done
+ # Stop tracing forcing full buffer consumption
+ stop_lttng_tracing $SESSION_NAME
+
+ # Check for notifications reception
+ wait_for_message "${low_output_file_pattern}" "notification: low $i"
+ ret=$?
+ ok $ret "Notifications $i received"
+ if [[ $ret -ne "0" ]]; then
+ # Error occurred bail out
+ break;
+ fi
+ done
+
+ wait_for_message "${low_output_file_pattern}" "exit: 0"
+ ret=$?
+ ok $ret "Application for low notification terminated normally"
+ if [[ $ret -eq "0" ]]; then
+ rm ${CURDIR}/${low_output_file_pattern}* 2> /dev/null
+ else
+ # Keep the file
+ print_errors "${low_output_file_pattern}"
+ fi
+
+ wait_for_message "${high_output_file_pattern}" "exit: 0"
+ ret=$?
+ ok $ret "Application for high notification terminated normally"
+ if [[ $ret -eq "0" ]]; then
+ rm ${CURDIR}/${high_output_file_pattern}* 2> /dev/null
+ else
+ # Keep the file
+ print_errors "${high_output_file_pattern}"
+ fi
+
+ kill -9 $app_pid
+ wait $app_pid 2> /dev/null
+
+ stop_lttng_sessiond
+}
+
+
+TESTS=(
+ test_multi_app
+)
+
+for fct_test in ${TESTS[@]};
+do
+ TRACE_PATH=$(mktemp -d)
+
+ ${fct_test}
+ if [ $? -ne 0 ]; then
+ break;
+ fi
+
+ # Only delete if successful
+ rm -rf $TRACE_PATH
+done
+