Test: kernel testing for notification
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 28 Jul 2017 17:40:41 +0000 (13:40 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 12 Nov 2017 19:50:07 +0000 (14:50 -0500)
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 <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
tests/regression/Makefile.am
tests/regression/tools/notification/Makefile.am
tests/regression/tools/notification/base_client.c
tests/regression/tools/notification/notification.c
tests/regression/tools/notification/test_notification [deleted file]
tests/regression/tools/notification/test_notification_kernel [new file with mode: 0755]
tests/regression/tools/notification/test_notification_multi_app
tests/regression/tools/notification/test_notification_ust [new file with mode: 0755]
tests/utils/utils.sh

index c52c3c61491aa1c17ddadde732e8a9df5dedabb1..0f547a64d28a5e91cfbc4ae90090e6f201fd5e60 100644 (file)
@@ -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
index 707047c3a3ce9154dc6888d71e9e2b4db76bc3b6..e0b092aa55668aaa0db628025695dd78c084e093 100644 (file)
@@ -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:
index 7fbaa9e4dc77741047e43dffe9635733402172b3..5d801282ce565762f28b0c305025e4037fcddce9 100644 (file)
@@ -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;
index 5de09e2016e1ed33947780d11ab344d78fd76780..6c52bed01d864f8f40e574cd266dd0e5648584f8 100644 (file)
@@ -35,6 +35,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <poll.h>
 
 #include <lttng/action/action.h>
 #include <lttng/action/notify.h>
 #include <tap/tap.h>
 
 #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 (executable)
index 421abe0..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) - 2017 Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
-
-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 (executable)
index 0000000..b4c5958
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/bash
+#
+# Copyright (C) - 2017 Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+
+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
index d7f6319fd7a06919ac3099e433f5062bf8ff0c72..622a18aad37377f169012496787b8b9a899f9856 100755 (executable)
@@ -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 (executable)
index 0000000..70cbec6
--- /dev/null
@@ -0,0 +1,105 @@
+#!/bin/bash
+#
+# Copyright (C) - 2017 Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+
+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
index 567929aa08840f79e251855500b74f7584f36331..e8dfcda3cedf157c334d594bbc187d42020c4864 100644 (file)
@@ -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 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 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 0 "$@"
 
 }
 
 function destroy_lttng_session_fail ()
 {
-       destroy_lttng_session 1 "$@"
+       destroy_lttng_session 1 "$@"
 }
 
+function destroy_lttng_session_notap ()
+{
+       destroy_lttng_session 0 0 "$@"
+}
 
 function destroy_lttng_sessions ()
 {
This page took 0.039759 seconds and 4 git commands to generate.