From: Jonathan Rajotte Date: Fri, 28 Jul 2017 17:40:41 +0000 (-0400) Subject: Test: kernel testing for notification X-Git-Tag: v2.11.0-rc1~444 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=854382b8a0f18fa77ba97eac55a61dd8d8d8cc85 Test: kernel testing for notification Perform notification tests on both domains. Scenarios where low notifications are wanted need further synchronization since multiple low notifications can be sent between resume_consumer and the lttng stop command. This problem can be addressed by suspending the generation of events. This is achieved by the use of signal-aware background shells and the use of lttng-test kernel module or gen-ust-events as events generator. These background shells are controlled by signal SIGUSR1 and provide their states via a state file. If the file is present the application is suspended and does not generate events, otherwise events are generated. Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau --- diff --git a/tests/regression/Makefile.am b/tests/regression/Makefile.am index c52c3c614..0f547a64d 100644 --- a/tests/regression/Makefile.am +++ b/tests/regression/Makefile.am @@ -24,7 +24,8 @@ TESTS = tools/filtering/test_invalid_filter \ tools/crash/test_crash \ tools/regen-metadata/test_ust \ tools/regen-statedump/test_ust \ - tools/notification/test_notification \ + tools/notification/test_notification_ust \ + tools/notification/test_notification_kernel \ tools/notification/test_notification_multi_app if HAVE_LIBLTTNG_UST_CTL diff --git a/tests/regression/tools/notification/Makefile.am b/tests/regression/tools/notification/Makefile.am index 707047c3a..e0b092aa5 100644 --- a/tests/regression/tools/notification/Makefile.am +++ b/tests/regression/tools/notification/Makefile.am @@ -10,7 +10,7 @@ noinst_PROGRAMS = base_client notification if NO_SHARED CLEANFILES = libpause_consumer.so libpause_consumer.so.debug -EXTRA_DIST = test_notification test_notification_multi_app base_client.c notification.c consumer_testpoints.c +EXTRA_DIST = test_notification_ust test_notification_kernel test_notification_multi_app base_client.c notification.c consumer_testpoints.c else @@ -30,8 +30,7 @@ base_client_LDADD = $(LIB_LTTNG_CTL) notification_SOURCES = notification.c notification_LDADD = $(LIB_LTTNG_CTL) $(LIBTAP) -lm -noinst_SCRIPTS = test_notification test_notification_multi_app -EXTRA_DIST = test_notification test_notification_multi_app +noinst_SCRIPTS = test_notification_ust test_notification_ust test_notification_multi_app all-local: diff --git a/tests/regression/tools/notification/base_client.c b/tests/regression/tools/notification/base_client.c index 7fbaa9e4d..5d801282c 100644 --- a/tests/regression/tools/notification/base_client.c +++ b/tests/regression/tools/notification/base_client.c @@ -201,7 +201,7 @@ int main(int argc, char **argv) goto end; } condition_status = lttng_condition_buffer_usage_set_domain_type( - condition, LTTNG_DOMAIN_UST); + condition, domain_type); if (condition_status != LTTNG_CONDITION_STATUS_OK) { printf("error: Could not set domain type\n"); ret = 1; diff --git a/tests/regression/tools/notification/notification.c b/tests/regression/tools/notification/notification.c index 5de09e201..6c52bed01 100644 --- a/tests/regression/tools/notification/notification.c +++ b/tests/regression/tools/notification/notification.c @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #include #include @@ -51,8 +54,37 @@ #include #define NUM_TESTS 104 + int nb_args = 0; int named_pipe_args_start = 0; +pid_t app_pid = -1; +const char *app_state_file = NULL; + +static +void wait_on_file(const char *path, bool file_exist) +{ + if (!path) { + return; + } + for (;;) { + int ret; + struct stat buf; + + ret = stat(path, &buf); + if (ret == -1 && errno == ENOENT) { + if (file_exist) { + (void) poll(NULL, 0, 10); /* 10 ms delay */ + continue; /* retry */ + } + break; /* File does not exist */ + } + if (ret) { + perror("stat"); + exit(EXIT_FAILURE); + } + break; /* found */ + } +} int write_pipe(const char *path, uint8_t data) { @@ -103,6 +135,64 @@ int resume_consumer(const char **argv) return ret; } +int suspend_application() +{ + int ret; + struct stat buf; + + if (!stat(app_state_file, &buf)) { + fail("App is already in a suspended state."); + ret = -1; + goto error; + } + + /* + * Send SIGUSR1 to application instructing it to bypass tracepoint. + */ + ret = kill(app_pid, SIGUSR1); + if (ret) { + fail("SIGUSR1 failed. errno %d", errno); + ret = -1; + goto error; + } + + wait_on_file(app_state_file, true); + +error: + return ret; + +} + +int resume_application() +{ + int ret; + struct stat buf; + + ret = stat(app_state_file, &buf); + if (ret == -1 && errno == ENOENT) { + fail("State file does not exist"); + goto error; + } + if (ret) { + perror("stat"); + goto error; + } + + ret = kill(app_pid, SIGUSR1); + if (ret) { + fail("SIGUSR1 failed. errno %d", errno); + ret = -1; + goto error; + } + + wait_on_file(app_state_file, false); + +error: + return ret; + +} + + void test_triggers_buffer_usage_condition(const char *session_name, const char *channel_name, enum lttng_domain_type domain_type, @@ -284,7 +374,7 @@ end: lttng_action_destroy(action); } -void test_notification_channel(const char *session_name, const char *channel_name, enum lttng_domain_type domain_type, const char **argv) +void test_notification_channel(const char *session_name, const char *channel_name, const enum lttng_domain_type domain_type, const char **argv) { int ret = 0; enum lttng_condition_status condition_status; @@ -497,6 +587,7 @@ void test_notification_channel(const char *session_name, const char *channel_nam lttng_notification_destroy(notification); notification = NULL; + suspend_application(); resume_consumer(argv); lttng_stop_tracing(session_name); @@ -520,6 +611,7 @@ void test_notification_channel(const char *session_name, const char *channel_nam notification = NULL; /* Stop consumer to force a high notification */ + resume_application(); lttng_start_tracing(session_name); stop_consumer(argv); @@ -530,6 +622,7 @@ void test_notification_channel(const char *session_name, const char *channel_nam lttng_notification_destroy(notification); notification = NULL; + suspend_application(); /* Resume consumer to allow event consumption */ resume_consumer(argv); lttng_stop_tracing(session_name); @@ -541,6 +634,7 @@ void test_notification_channel(const char *session_name, const char *channel_nam lttng_notification_destroy(notification); notification = NULL; + resume_application(); /* Stop consumer to force a high notification */ lttng_start_tracing(session_name); stop_consumer(argv); @@ -580,19 +674,21 @@ int main(int argc, const char *argv[]) plan_tests(NUM_TESTS); - /* Argument 4 and upward are named pipe location for consumerd control */ - named_pipe_args_start = 4; + /* Argument 6 and upward are named pipe location for consumerd control */ + named_pipe_args_start = 6; - if (argc < 5) { + if (argc < 7) { fail("Missing parameter for tests to run %d", argc); goto error; } nb_args = argc; - session_name = argv[1]; - channel_name = argv[2]; - domain_type_string= argv[3]; + domain_type_string = argv[1]; + session_name = argv[2]; + channel_name = argv[3]; + app_pid = (pid_t) atoi(argv[4]); + app_state_file = argv[5]; if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string)) { domain_type = LTTNG_DOMAIN_UST; diff --git a/tests/regression/tools/notification/test_notification b/tests/regression/tools/notification/test_notification deleted file mode 100755 index 421abe0ee..000000000 --- a/tests/regression/tools/notification/test_notification +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# -# Copyright (C) - 2017 Jonathan Rajotte-Julien -# -# 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 - -CURDIR=$(dirname $0)/ -TESTDIR=$CURDIR/../../../ - -#This is needed since the testpoint create a pipe with the consumerd type 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" -CHANNEL_NAME="my_ust_channel" -EVENT_NAME="tp:tptest" - -TRACE_PATH=$(mktemp -d) -PAGE_SIZE=$(getconf PAGE_SIZE) - -DIR=$(readlink -f $TESTDIR) - -source $TESTDIR/utils/utils.sh - -consumerd_pipe=() - -file_sync_after_first_event=$(mktemp -u) - -LTTNG_SESSIOND_ENV_VARS="LTTNG_TESTPOINT_ENABLE=1 CONSUMER_PAUSE_PIPE_PATH=${TESTPOINT_PIPE_PATH} LD_PRELOAD=${TESTPOINT}" -start_lttng_sessiond_notap - -create_lttng_session_notap $SESSION_NAME $TRACE_PATH - -enable_ust_lttng_channel_notap $SESSION_NAME $CHANNEL_NAME --subbuf-size=$PAGE_SIZE -enable_ust_lttng_event_notap $SESSION_NAME $EVENT_NAME $CHANNEL_NAME - -#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 - - -# 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 - -while [ ! -f "${file_sync_after_first_event}" ]; do - sleep 0.5 -done -rm ${file_sync_after_first_event} - -# The actual test suite -# TODO: Add support for kernel domain -$CURDIR/notification $SESSION_NAME $CHANNEL_NAME LTTNG_DOMAIN_UST ${consumerd_pipe[@]} - -stop_lttng_sessiond_notap - -# On ungraceful kill the app is cleaned up via the full_cleanup call -# Suppress kill message -kill -9 $APP_PID -wait $APP_PID 2> /dev/null - -# Just in case cleanup -rm -rf $TRACE_PATH -rm ${consumerd_pipe[@]} 2> /dev/null diff --git a/tests/regression/tools/notification/test_notification_kernel b/tests/regression/tools/notification/test_notification_kernel new file mode 100755 index 000000000..b4c5958b5 --- /dev/null +++ b/tests/regression/tools/notification/test_notification_kernel @@ -0,0 +1,117 @@ +#!/bin/bash +# +# Copyright (C) - 2017 Jonathan Rajotte-Julien +# +# 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 + +CURDIR=$(dirname $0)/ +TESTDIR=$CURDIR/../../../ + +#This is needed since the testpoint create a pipe with the consumerd type 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" +TESTAPP_STATE_PATH=$(mktemp -u "$CURDIR/application_state.XXXXXXXXXX") + +NR_ITER=-1 +NR_USEC_WAIT=5 + +SESSION_NAME="my_session" +CHANNEL_NAME="my_channel" + +TRACE_PATH=$(mktemp -d) +PAGE_SIZE=$(getconf PAGE_SIZE) + +DIR=$(readlink -f $TESTDIR) +NUM_TESTS=104 + +source $TESTDIR/utils/utils.sh + +function kernel_event_generator_toogle_state +{ + kernel_event_generator_suspended=$((kernel_event_generator_suspended==0)) + +} +function kernel_event_generator +{ + state_file=$1 + kernel_event_generator_suspended=0 + trap kernel_event_generator_toogle_state SIGUSR1 + trap "exit" SIGTERM SIGINT EXIT + while (true); do + if [[ $kernel_event_generator_suspended -eq "1" ]]; then + touch $state_file + sleep 0.5 + else + if [[ -f $state_file ]]; then + rm $state_file 2> /dev/null + fi + echo -n "1000" > /proc/lttng-test-filter-event 2> /dev/null + fi + done +} + +function kernel_test +{ + local consumerd_pipe=() + local event_name="lttng_test_filter_event" + + modprobe lttng-test + + LTTNG_SESSIOND_ENV_VARS="LTTNG_TESTPOINT_ENABLE=1 CONSUMER_PAUSE_PIPE_PATH=${TESTPOINT_PIPE_PATH} LD_PRELOAD=${TESTPOINT}" + start_lttng_sessiond_notap + + create_lttng_session_notap $SESSION_NAME $TRACE_PATH + + lttng_enable_kernel_channel_notap $SESSION_NAME $CHANNEL_NAME --subbuf-size=$PAGE_SIZE + enable_kernel_lttng_event_notap $SESSION_NAME $event_name $CHANNEL_NAME + + #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 + + kernel_event_generator $TESTAPP_STATE_PATH & + APP_PID=$! + + $CURDIR/notification LTTNG_DOMAIN_KERNEL $SESSION_NAME $CHANNEL_NAME $APP_PID $TESTAPP_STATE_PATH ${consumerd_pipe[@]} + + destroy_lttng_session_notap $SESSION_NAME + stop_lttng_sessiond_notap + + kill -9 $APP_PID + wait $APP_PID 2> /dev/null + + + rmmod lttng-test + + rm ${consumerd_pipe[@]} 2> /dev/null +} + +if [ "$(id -u)" == "0" ]; then + kernel_test +else + # Kernel tests are skipped. + plan_tests $NUM_TESTS + skip 0 "Root access is needed. Skipping all kernel notification tests." $NUM_TESTS +fi + +# Just in case cleanup +rm -rf $TRACE_PATH diff --git a/tests/regression/tools/notification/test_notification_multi_app b/tests/regression/tools/notification/test_notification_multi_app index d7f6319fd..622a18aad 100755 --- a/tests/regression/tools/notification/test_notification_multi_app +++ b/tests/regression/tools/notification/test_notification_multi_app @@ -25,13 +25,13 @@ 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" +TESTAPP_STATE_FILE="$(mktemp -u)" -NR_ITER=-1 +NR_ITER=1000 NR_USEC_WAIT=5 SESSION_NAME="my_session" -UST_CHANNEL_NAME="my_ust_channel" -EVENT_NAME="tp:tptest" +CHANNEL_NAME="my_channel" TRACE_PATH=$(mktemp -d) @@ -40,7 +40,9 @@ DIR=$(readlink -f $TESTDIR) PAGE_SIZE=$(getconf PAGE_SIZE) -NUM_TESTS=62 +NUM_TEST_UST=50 +NUM_TEST_KERNEL=50 +NUM_TESTS=$(($NUM_TEST_UST + $NUM_TEST_KERNEL)) source $TESTDIR/utils/utils.sh @@ -54,6 +56,54 @@ print_test_banner "$TEST_DESC" app_pids=() +function kernel_event_generator_toogle_state +{ + kernel_event_generator_suspended=$((kernel_event_generator_suspended==0)) + +} +function kernel_event_generator +{ + state_file=$1 + kernel_event_generator_suspended=0 + trap kernel_event_generator_toogle_state SIGUSR1 + trap "exit" SIGTERM SIGINT + while (true); do + if [[ $kernel_event_generator_suspended -eq "1" ]]; then + touch $state_file + sleep 0.5 + else + if [[ -f $state_file ]]; then + rm $state_file 2> /dev/null + fi + echo -n "1000" > /proc/lttng-test-filter-event + fi + done +} + +function ust_event_generator_toogle_state +{ + ust_event_generator_suspended=$((ust_event_generator_suspended==0)) + +} +function ust_event_generator +{ + state_file=$1 + ust_event_generator_suspended=0 + trap ust_event_generator_toogle_state SIGUSR1 + trap "exit" SIGTERM SIGINT + while (true); do + if [[ $ust_event_generator_suspended -eq "1" ]]; then + touch $state_file + sleep 0.5 + else + if [[ -f $state_file ]]; then + rm $state_file 2> /dev/null + fi + taskset -c 0 $TESTAPP_BIN $NR_ITER $NR_USEC_WAIT > /dev/null 2>&1 + fi + done +} + function start_client { local pid=-1 local output_file=$1 @@ -120,25 +170,25 @@ 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 domain_type=$1 + local event_generator_pid=$2 + local app_pids=() local low_output_file_pattern="low_app_output_file_" local high_output_file_pattern="high_app_output_file_" @@ -148,6 +198,23 @@ function test_multi_app () local nr_notification_expected=5 local nr_client_app=50 + local domain_string="" + local event_name="" + + case $domain_type in + ust) + domain_string=LTTNG_DOMAIN_UST + event_name="tp:tptest" + ;; + kernel) + domain_string=LTTNG_DOMAIN_KERNEL + event_name="lttng_test_filter_event" + ;; + *) + fail "Invalid domain type" + exit 1 + ;; + esac # Cleanup rm ${CURDIR}/${low_output_file_pattern}* 2> /dev/null @@ -157,21 +224,9 @@ function test_multi_app () 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=$PAGE_SIZE - enable_ust_lttng_event_ok $SESSION_NAME $EVENT_NAME $UST_CHANNEL_NAME + enable_${domain_type}_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME --subbuf-size=$PAGE_SIZE + enable_${domain_type}_lttng_event_ok $SESSION_NAME $event_name $CHANNEL_NAME # Fetch consumerd testpoint pipe information # This is needed since the testpoint create a pipe with the consumer type suffixed @@ -182,8 +237,8 @@ function test_multi_app () 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 + start_client $low_app_output_file $SESSION_NAME $CHANNEL_NAME $domain_string LOW RATIO 0.0 $nr_notification_expected + start_client $high_app_output_file $SESSION_NAME $CHANNEL_NAME $domain_string HIGH RATIO 0.420 $nr_notification_expected done wait_for_message "${low_output_file_pattern}" "sync: ready" @@ -200,6 +255,13 @@ function test_multi_app () wait_for_message "${high_output_file_pattern}" "notification: high $i" + # Put application in suspend mode to prevent double low + # notification and synchronize on state file. + kill -s SIGUSR1 $event_generator_pid + while [ ! -f "${TESTAPP_STATE_FILE}" ]; do + sleep 0.5 + done + # Resume consumerd for pipe in "${consumerd_pipe[@]}"; do resume_consumerd "${pipe}" @@ -215,6 +277,12 @@ function test_multi_app () # Error occurred bail out break; fi + + # Put application in active mode and synchronize on state file. + kill -s SIGUSR1 $event_generator_pid + while [ -f "${TESTAPP_STATE_FILE}" ]; do + sleep 0.5 + done done wait_for_message "${low_output_file_pattern}" "exit: 0" @@ -237,42 +305,118 @@ function test_multi_app () print_errors "${high_output_file_pattern}" fi - kill -9 $app_pid - wait $app_pid 2> /dev/null - + destroy_lttng_session_ok $SESSION_NAME stop_lttng_sessiond + + for pipe in "${consumerd_pipe[@]}"; do + rm -rf "${pipe}" + done +} + +function test_multi_app_ust () +{ + diag "Multi client app UST notification" + ust_event_generator $TESTAPP_STATE_FILE & + local generator_pid=$! + + test_multi_app ust $generator_pid + + kill -9 $generator_pid 2> /dev/null + wait $generator_pid 2> /dev/null + rm -rf ${TESTAPP_STATE_FILE} 2> /dev/null +} + +function test_multi_app_kernel () +{ + diag "Multi client app kernel notification" + modprobe lttng-test + + kernel_event_generator $TESTAPP_STATE_FILE & + local generator_pid=$! + + test_multi_app kernel $generator_pid + + + kill -9 $generator_pid 2>/dev/null + wait $generator_pid 2> /dev/null + rm -rf ${TESTAPP_STATE_FILE} 2> /dev/null + + rmmod lttng-test +} + +function test_on_register_evaluation_ust () +{ + diag "On register notification UST" + + # Start app in infinite loop + ust_event_generator $TESTAPP_STATE_FILE & + local generator_pid=$! + + test_on_register_evaluation ust $generator_pid + + kill -9 $generator_pid 2> /dev/null + wait $generator_pid 2> /dev/null + rm -rf ${TESTAPP_STATE_FILE} 2> /dev/null + +} + +function test_on_register_evaluation_kernel() +{ + diag "On register notification kernel" + + modprobe lttng-test + + kernel_event_generator $TESTAPP_STATE_FILE & + local generator_pid=$! + + test_on_register_evaluation kernel $generator_pid + + + kill -9 $generator_pid 2> /dev/null + wait $generator_pid 2> /dev/null + rm -rf ${TESTAPP_STATE_FILE} 2> /dev/null + + rmmod lttng-test } function test_on_register_evaluation () { + local domain_type=$1 + local event_generator_pid=$2 + local app_pids=() local high_output_file_pattern="high_app_output_file_on_register_evaluation" local testpoint_base_path=$(readlink -f "$CURDIR/lttng.t_p_n_register_evaluation") local testpoint_pipe_path=$(mktemp -u "${testpoint_base_path}.XXXXXX") + local domain_string="" + local event_name="" # Cleanup rm ${CURDIR}/${high_output_file_pattern}* 2> /dev/null + case $domain_type in + ust) + domain_string=LTTNG_DOMAIN_UST + event_name="tp:tptest" + ;; + kernel) + domain_string=LTTNG_DOMAIN_KERNEL + event_name="lttng_test_filter_event" + ;; + *) + fail "Invalid domain type" + exit 1 + ;; + esac + # 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=$PAGE_SIZE - enable_ust_lttng_event_ok $SESSION_NAME $EVENT_NAME $UST_CHANNEL_NAME + enable_${domain_type}_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME --subbuf-size=$PAGE_SIZE + enable_${domain_type}_lttng_event_ok $SESSION_NAME $event_name $CHANNEL_NAME # Fetch consumerd testpoint pipe information # This is needed since the testpoint create a pipe with the consumer type suffixed @@ -282,7 +426,7 @@ function test_on_register_evaluation () high_app_output_file=${high_output_file_pattern}.first_receiver high_app_output_path=$CURDIR/${high_app_output_file} - start_client $high_app_output_path $SESSION_NAME $UST_CHANNEL_NAME LTTNG_DOMAIN_UST HIGH RATIO 0.420 1 + start_client $high_app_output_path $SESSION_NAME $CHANNEL_NAME $domain_string HIGH RATIO 0.420 1 wait_for_message "${high_app_output_file}" "sync: ready" @@ -299,7 +443,7 @@ function test_on_register_evaluation () # notification on subscription high_app_output_file=${high_output_file_pattern}.second_receiver high_app_output_path=$CURDIR/${high_app_output_file} - start_client $high_app_output_path $SESSION_NAME $UST_CHANNEL_NAME LTTNG_DOMAIN_UST HIGH RATIO 0.420 1 + start_client $high_app_output_path $SESSION_NAME $CHANNEL_NAME $domain_string HIGH RATIO 0.420 1 wait_for_message "${high_app_output_file}" "sync: ready" wait_for_message "${high_app_output_file}" "notification: high 0" @@ -318,18 +462,34 @@ function test_on_register_evaluation () print_errors "${high_output_file_pattern}" fi + destroy_lttng_session_ok $SESSION_NAME stop_lttng_sessiond - kill -9 $app_pid - wait $app_pid 2> /dev/null + kill -9 $generator_pid + wait $generator_pid 2> /dev/null + + for pipe in "${consumerd_pipe[@]}"; do + rm -rf "${pipe}" + done + } TESTS=( - test_multi_app - test_on_register_evaluation + test_multi_app_ust + test_on_register_evaluation_ust ) +if [ "$(id -u)" == "0" ]; then + TESTS+=( + test_multi_app_kernel + test_on_register_evaluation_kernel +) +else + skip 0 "Root access is needed. Skipping all kernel multi-app notification tests." $NUM_TEST_KERNEL +fi + + for fct_test in ${TESTS[@]}; do TRACE_PATH=$(mktemp -d) @@ -342,4 +502,3 @@ do # Only delete if successful rm -rf $TRACE_PATH done - diff --git a/tests/regression/tools/notification/test_notification_ust b/tests/regression/tools/notification/test_notification_ust new file mode 100755 index 000000000..70cbec6fe --- /dev/null +++ b/tests/regression/tools/notification/test_notification_ust @@ -0,0 +1,105 @@ +#!/bin/bash +# +# Copyright (C) - 2017 Jonathan Rajotte-Julien +# +# 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 + +CURDIR=$(dirname $0)/ +TESTDIR=$CURDIR/../../../ + +#This is needed since the testpoint create a pipe with the consumerd type 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" +TESTAPP_STATE_PATH=$(mktemp -u "$CURDIR/application_state.XXXXXXXXXX") + +NR_ITER=1000 +NR_USEC_WAIT=5 + +SESSION_NAME="my_session" +CHANNEL_NAME="my_channel" + +TRACE_PATH=$(mktemp -d) +PAGE_SIZE=$(getconf PAGE_SIZE) + +DIR=$(readlink -f $TESTDIR) + + +source $TESTDIR/utils/utils.sh + +function ust_event_generator_toogle_state +{ + ust_event_generator_suspended=$((ust_event_generator_suspended==0)) + +} +function ust_event_generator +{ + state_file=$1 + ust_event_generator_suspended=0 + trap ust_event_generator_toogle_state SIGUSR1 + trap "exit" SIGTERM SIGINT + while (true); do + if [[ $ust_event_generator_suspended -eq "1" ]]; then + touch $state_file + sleep 0.5 + else + if [[ -f $state_file ]]; then + rm $state_file 2> /dev/null + fi + taskset -c 0 $TESTAPP_BIN $NR_ITER $NR_USEC_WAIT > /dev/null 2>&1 + fi + done +} + +consumerd_pipe=() +file_sync_after_first_event=$(mktemp -u) +event_name="tp:tptest" + +LTTNG_SESSIOND_ENV_VARS="LTTNG_TESTPOINT_ENABLE=1 CONSUMER_PAUSE_PIPE_PATH=${TESTPOINT_PIPE_PATH} LD_PRELOAD=${TESTPOINT}" +start_lttng_sessiond_notap + +create_lttng_session_notap $SESSION_NAME $TRACE_PATH + +enable_ust_lttng_channel_notap $SESSION_NAME $CHANNEL_NAME --subbuf-size=$PAGE_SIZE +enable_ust_lttng_event_notap $SESSION_NAME $event_name $CHANNEL_NAME + +#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 + + +ust_event_generator $TESTAPP_STATE_PATH & +APP_PID=$! + +$CURDIR/notification LTTNG_DOMAIN_UST $SESSION_NAME $CHANNEL_NAME $APP_PID $TESTAPP_STATE_PATH ${consumerd_pipe[@]} + +destroy_lttng_session_notap $SESSION_NAME +stop_lttng_sessiond_notap + +# On ungraceful kill the app is cleaned up via the full_cleanup call +# Suppress kill message +kill -9 $APP_PID +wait $APP_PID 2> /dev/null +rm ${consumerd_pipe[@]} 2> /dev/null +rm ${TESTAPP_STATE_PATH} 2> /dev/null + +# Just in case cleanup +rm -rf $TRACE_PATH diff --git a/tests/utils/utils.sh b/tests/utils/utils.sh index 567929aa0..e8dfcda3c 100644 --- a/tests/utils/utils.sh +++ b/tests/utils/utils.sh @@ -127,10 +127,11 @@ function conf_proc_count() function enable_kernel_lttng_event { - local expected_to_fail="$1" - local sess_name="$2" - local event_name="$3" - local channel_name="$4" + local withtap="$1" + local expected_to_fail="$2" + local sess_name="$3" + local event_name="$4" + local channel_name="$5" if [ -z "$event_name" ]; then # Enable all event if no event name specified @@ -148,20 +149,30 @@ function enable_kernel_lttng_event ret=$? if [[ $expected_to_fail -eq "1" ]]; then test $ret -ne "0" - ok $? "Enable kernel event $event_name for session $session_name on channel $channel_name failed as expected" + ret=$? + if [ $withtap -eq "1" ]; then + ok $ret "Enable kernel event $event_name for session $session_name on channel $channel_name failed as expected" + fi else - ok $ret "Enable kernel event $event_name for session $sess_name" + if [ $withtap -eq "1" ]; then + ok $ret "Enable kernel event $event_name for session $sess_name" + fi fi } function enable_kernel_lttng_event_ok () { - enable_kernel_lttng_event 0 "$@" + enable_kernel_lttng_event 1 0 "$@" } function enable_kernel_lttng_event_fail () { - enable_kernel_lttng_event 1 "$@" + enable_kernel_lttng_event 1 1 "$@" +} + +function enable_kernel_lttng_event_notap () +{ + enable_kernel_lttng_event 0 0 "$@" } # Old interface @@ -251,28 +262,45 @@ function lttng_disable_kernel_syscall_fail() function lttng_enable_kernel_channel() { - local expected_to_fail=$1 - local sess_name=$2 - local channel_name=$3 + local withtap=$1 + local expected_to_fail=$2 + local sess_name=$3 + local channel_name=$4 + local opt=$5 - $TESTDIR/../src/bin/lttng/$LTTNG_BIN enable-channel -k $channel_name -s $sess_name 1> $OUTPUT_DEST 2> $ERROR_OUTPUT_DEST + $TESTDIR/../src/bin/lttng/$LTTNG_BIN enable-channel -k $channel_name -s $sess_name $opt 1> $OUTPUT_DEST 2> $ERROR_OUTPUT_DEST ret=$? if [[ $expected_to_fail -eq "1" ]]; then test "$ret" -ne "0" - ok $? "Enable channel $channel_name for session $sess_name failed as expected" + ret=$? + if [ $withtap -eq "1" ]; then + ok $ret "Enable channel $channel_name for session $sess_name failed as expected" + fi else - ok $ret "Enable channel $channel_name for session $sess_name" + if [ $withtap -eq "1" ]; then + ok $ret "Enable channel $channel_name for session $sess_name" + fi fi } function lttng_enable_kernel_channel_ok() { - lttng_enable_kernel_channel 0 "$@" + lttng_enable_kernel_channel 1 0 "$@" } function lttng_enable_kernel_channel_fail() { - lttng_enable_kernel_channel 1 "$@" + lttng_enable_kernel_channel 1 1 "$@" +} + +function lttng_enable_kernel_channel_notap() +{ + lttng_enable_kernel_channel 0 0 "$@" +} + +function enable_kernel_lttng_channel_ok() +{ + lttng_enable_kernel_channel 1 0 "$@" } function lttng_disable_kernel_channel() @@ -1086,30 +1114,40 @@ function stop_lttng_tracing_fail () function destroy_lttng_session () { - local expected_to_fail=$1 - local sess_name=$2 + local withtap=$1 + local expected_to_fail=$2 + local sess_name=$3 $TESTDIR/../src/bin/lttng/$LTTNG_BIN destroy $sess_name 1> $OUTPUT_DEST 2> $ERROR_OUTPUT_DEST ret=$? if [[ $expected_to_fail -eq "1" ]]; then test "$ret" -ne "0" - ok $? "Destroy session $sess_name failed as expected" + ret=$? + if [ $withtap -eq "1" ]; then + ok $ret "Destroy session $sess_name failed as expected" + fi else - ok $ret "Destroy session $sess_name" + if [ $withtap -eq "1" ]; then + ok $ret "Destroy session $sess_name" + fi fi } function destroy_lttng_session_ok () { - destroy_lttng_session 0 "$@" + destroy_lttng_session 1 0 "$@" } function destroy_lttng_session_fail () { - destroy_lttng_session 1 "$@" + destroy_lttng_session 1 1 "$@" } +function destroy_lttng_session_notap () +{ + destroy_lttng_session 0 0 "$@" +} function destroy_lttng_sessions () {