diff --git a/.gitignore b/.gitignore index 1ad59422bd..abc12685ad 100644 --- a/.gitignore +++ b/.gitignore @@ -116,6 +116,7 @@ health_check /tests/utils/testapp/gen-ust-events/gen-ust-events /tests/utils/testapp/gen-ust-nevents-str/gen-ust-nevents-str /tests/utils/testapp/gen-ust-nevents/gen-ust-nevents +/tests/utils/testapp/gen-ust-statedump-events/gen-ust-statedump-events /tests/utils/testapp/gen-ust-tracef/gen-ust-tracef /tests/utils/testapp/gen-syscall-events/gen-syscall-events /tests/regression/tools/live/live_test diff --git a/configure.ac b/configure.ac index acae225ad7..bbe7a795d7 100644 --- a/configure.ac +++ b/configure.ac @@ -1143,6 +1143,7 @@ AC_CONFIG_FILES([ tests/regression/ust/clock-override/Makefile tests/regression/ust/type-declarations/Makefile tests/regression/ust/rotation-destroy-flush/Makefile + tests/regression/ust/statedump-notifier/Makefile tests/regression/ust/blocking/Makefile tests/stress/Makefile tests/unit/Makefile @@ -1156,6 +1157,7 @@ AC_CONFIG_FILES([ tests/utils/testapp/gen-ust-nevents/Makefile tests/utils/testapp/gen-ust-nevents-str/Makefile tests/utils/testapp/gen-syscall-events/Makefile + tests/utils/testapp/gen-ust-statedump-events/Makefile tests/utils/testapp/gen-ust-tracef/Makefile ]) diff --git a/tests/fast_regression b/tests/fast_regression index 0c44c5a231..de101be075 100644 --- a/tests/fast_regression +++ b/tests/fast_regression @@ -31,6 +31,7 @@ regression/ust/python-logging/test_python_logging regression/ust/getcpu-override/test_getcpu_override regression/ust/clock-override/test_clock_override regression/ust/rotation-destroy-flush/test_rotation_destroy_flush +regression/ust/statedump-notifier/test_statedump_notifier regression/ust/blocking/test_blocking regression/ust/test_event_basic regression/ust/test_event_tracef diff --git a/tests/regression/Makefile.am b/tests/regression/Makefile.am index 50e89e4c52..53ff649bc4 100644 --- a/tests/regression/Makefile.am +++ b/tests/regression/Makefile.am @@ -47,7 +47,8 @@ TESTS += ust/before-after/test_before_after \ ust/test_event_tracef \ ust/test_event_perf \ ust/blocking/test_blocking \ - ust/multi-lib/test_multi_lib + ust/multi-lib/test_multi_lib \ + ust/statedump-notifier/test_statedump_notifier endif # HAVE_LIBLTTNG_UST_CTL if PYTHON_BINDING diff --git a/tests/regression/ust/statedump-notifier/Makefile.am b/tests/regression/ust/statedump-notifier/Makefile.am new file mode 100644 index 0000000000..bad3f0e379 --- /dev/null +++ b/tests/regression/ust/statedump-notifier/Makefile.am @@ -0,0 +1,16 @@ +noinst_SCRIPTS = test_statedump_notifier +EXTRA_DIST = test_statedump_notifier + +all-local: + @if [ x"$(srcdir)" != x"$(builddir)" ]; then \ + for script in $(EXTRA_DIST); do \ + cp -f $(srcdir)/$$script $(builddir); \ + done; \ + fi + +clean-local: + @if [ x"$(srcdir)" != x"$(builddir)" ]; then \ + for script in $(EXTRA_DIST); do \ + rm -f $(builddir)/$$script; \ + done; \ + fi diff --git a/tests/regression/ust/statedump-notifier/test_statedump_notifier b/tests/regression/ust/statedump-notifier/test_statedump_notifier new file mode 100755 index 0000000000..8c91f0e20a --- /dev/null +++ b/tests/regression/ust/statedump-notifier/test_statedump_notifier @@ -0,0 +1,309 @@ +#!/bin/bash +# +# Copyright (C) - 2018 Geneviève Bastien +# +# 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 - Statedump Notifier" + +CURDIR=$(dirname $0)/ +TESTDIR=$CURDIR/../../.. +SESSION_NAME="statedump_notifier" + +TESTAPP_PATH="$TESTDIR/utils/testapp" +TESTAPP_NAME="gen-ust-statedump-events" +TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME/$TESTAPP_NAME" +NUM_EVENT=1000000 +NUM_STDP_EVENTS=2 +EVENT_NAME="tp:tpteststdmp" +CHANNEL_NAME="testchan" +PAGE_SIZE=$(getconf PAGE_SIZE) +SIZE_LIMIT=$PAGE_SIZE +NUM_TESTS=76 + +# Ensure the daemons invoke abort on error. +export LTTNG_ABORT_ON_ERROR=1 + +source $TESTDIR/utils/utils.sh + +# MUST set TESTDIR before calling those functions +function run_app_bg() +{ + file_termination=$1 + local file_initialization=$(mktemp -u) + + $TESTAPP_BIN -1 ${STATEDUMP_FILE} ${file_initialization} ${file_termination} & + ok $? "Running application in background" + + while [ ! -f "${file_initialization}" ]; do + sleep 0.5 + done + + rm -f ${file_initialization} +} + +function run_app_fg() +{ + $TESTAPP_BIN 0 ${STATEDUMP_FILE} + while [ ! -f "${STATEDUMP_FILE}" ]; do + sleep 0.5 + done + ok $? "Ran application in foreground" +} + +function test_statedump_notifier_enable_all_ust() +{ + + diag "Test statedump notifier enabling all ust events" + + start_lttng_sessiond + + create_lttng_session_ok $SESSION_NAME $TRACE_PATH + enable_ust_lttng_event_ok $SESSION_NAME "-a" + start_lttng_tracing_ok $SESSION_NAME + + run_app_fg + + # stop and destroy + stop_lttng_tracing_ok $SESSION_NAME + destroy_lttng_session_ok $SESSION_NAME + + # Validate the statedump events are present + trace_matches $EVENT_NAME $NUM_STDP_EVENTS $TRACE_PATH + + stop_lttng_sessiond +} + +function test_statedump_regenerate() +{ + diag "Test regenerating the statedump" + local file_termination=$(mktemp -u) + + start_lttng_sessiond + + create_lttng_session_ok $SESSION_NAME $TRACE_PATH + enable_ust_lttng_event_ok $SESSION_NAME "-a" + start_lttng_tracing_ok $SESSION_NAME + + # Run the app in the background to regenerate statedump + run_app_bg ${file_termination} + while [ ! -f "${STATEDUMP_FILE}" ]; do + sleep 0.5 + done + + rm $STATEDUMP_FILE + + # stop and destroy + regenerate_statedump_ok $SESSION_NAME + while [ ! -f "${STATEDUMP_FILE}" ]; do + sleep 0.5 + done + + touch ${file_termination} + + stop_lttng_tracing_ok $SESSION_NAME + destroy_lttng_session_ok $SESSION_NAME + + NUM_EVENTS=$((2*$NUM_STDP_EVENTS)) + + # Validate the statedump events are present + trace_matches $EVENT_NAME $NUM_EVENTS $TRACE_PATH + + rm -f ${file_termination} + stop_lttng_sessiond +} + +function test_statedump_enable_only_this() +{ + diag "Test statedump notifier enabling only statedump events" + + start_lttng_sessiond + + create_lttng_session_ok $SESSION_NAME $TRACE_PATH + enable_ust_lttng_event_ok $SESSION_NAME $EVENT_NAME + start_lttng_tracing_ok $SESSION_NAME + + run_app_fg + + # stop and destroy + stop_lttng_tracing_ok $SESSION_NAME + destroy_lttng_session_ok $SESSION_NAME + + # Validate the statedump events are present + trace_match_only $EVENT_NAME $NUM_STDP_EVENTS $TRACE_PATH + + stop_lttng_sessiond +} + +function test_statedump_enable_others() +{ + diag "Test statedump notifier when the events are not enabled" + + start_lttng_sessiond + + create_lttng_session_ok $SESSION_NAME $TRACE_PATH + enable_ust_lttng_event_ok $SESSION_NAME "lttng_ust_statedump:*" + start_lttng_tracing_ok $SESSION_NAME + + run_app_fg + + # stop and destroy + stop_lttng_tracing_ok $SESSION_NAME + destroy_lttng_session_ok $SESSION_NAME + + # Validate the statedump events are present + trace_matches $EVENT_NAME 0 $TRACE_PATH + + stop_lttng_sessiond +} + +function test_statedump_multi_session() +{ + diag "Test statedump with multiple sessions, with only one having the app statedump enabled" + + start_lttng_sessiond + + # BEFORE application is spawned, start 2 sessions + # Session 0 enables statedump events + create_lttng_session_ok "$SESSION_NAME-0" "$TRACE_PATH/0" + enable_ust_lttng_event_ok "$SESSION_NAME-0" "$EVENT_NAME" + start_lttng_tracing_ok "$SESSION_NAME-0" + + # Session 1 enables other ust events + create_lttng_session_ok "$SESSION_NAME-1" "$TRACE_PATH/1" + enable_ust_lttng_event_ok "$SESSION_NAME-1" "lttng_ust_statedump:*" + start_lttng_tracing_ok "$SESSION_NAME-1" + + # Run the app in foreground + run_app_fg + + # Close and destroy sessions + stop_lttng_tracing_ok "$SESSION_NAME-0" + destroy_lttng_session_ok "$SESSION_NAME-0" + stop_lttng_tracing_ok "$SESSION_NAME-1" + destroy_lttng_session_ok "$SESSION_NAME-1" + + # Validate traces + trace_match_only $EVENT_NAME $NUM_STDP_EVENTS $TRACE_PATH/0 + trace_matches $EVENT_NAME 0 $TRACE_PATH/1 + + stop_lttng_sessiond +} + +function test_statedump_app_already_alive() +{ + diag "Test the statedump notifier when the application was already started" + + # Run the app in the background to regenerate statedump + local file_termination=$(mktemp -u) + run_app_bg ${file_termination} + + start_lttng_sessiond + + create_lttng_session_ok $SESSION_NAME $TRACE_PATH + enable_ust_lttng_event_ok $SESSION_NAME $EVENT_NAME + start_lttng_tracing_ok $SESSION_NAME + + while [ ! -f "${STATEDUMP_FILE}" ]; do + sleep 0.5 + done + + # Kill the application + touch ${file_termination} + + # stop and destroy + stop_lttng_tracing_ok $SESSION_NAME + destroy_lttng_session_ok $SESSION_NAME + + # Validate the statedump events are present + trace_match_only $EVENT_NAME $NUM_STDP_EVENTS $TRACE_PATH + + stop_lttng_sessiond + rm -f ${file_termination} +} + +function test_statedump_app_running_multi_session() +{ + + diag "Test the statedump notifier, application already started, multi-session" + + # Run the app in the background + local file_termination=$(mktemp -u) + run_app_bg ${file_termination} + + start_lttng_sessiond + + # Start 2 sessions + # Session 0 enables statedump events + create_lttng_session_ok "$SESSION_NAME-0" "$TRACE_PATH/0" + enable_ust_lttng_event_ok "$SESSION_NAME-0" "$EVENT_NAME" + start_lttng_tracing_ok "$SESSION_NAME-0" + + # Session 1 enables other ust events + create_lttng_session_ok "$SESSION_NAME-1" "$TRACE_PATH/1" + enable_ust_lttng_event_ok "$SESSION_NAME-1" "lttng_ust_statedump:*" + start_lttng_tracing_ok "$SESSION_NAME-1" + + while [ ! -f "${STATEDUMP_FILE}" ]; do + sleep 0.5 + done + + # Kill the application + touch ${file_termination} + + # Close and destroy sessions + stop_lttng_tracing_ok "$SESSION_NAME-0" + destroy_lttng_session_ok "$SESSION_NAME-0" + stop_lttng_tracing_ok "$SESSION_NAME-1" + destroy_lttng_session_ok "$SESSION_NAME-1" + + # Validate traces + trace_match_only $EVENT_NAME $NUM_STDP_EVENTS $TRACE_PATH/0 + trace_matches $EVENT_NAME 0 $TRACE_PATH/1 + + stop_lttng_sessiond + rm -f ${file_termination} +} + +TESTS=( + "test_statedump_notifier_enable_all_ust" + "test_statedump_regenerate" + "test_statedump_enable_only_this" + "test_statedump_enable_others" + "test_statedump_multi_session" + "test_statedump_app_already_alive" + "test_statedump_app_running_multi_session" +) + +TEST_COUNT=${#TESTS[@]} +i=0 + +plan_tests $NUM_TESTS + +print_test_banner "$TEST_DESC" + +while [ "$i" -lt "$TEST_COUNT" ]; do + + trap signal_cleanup SIGTERM SIGINT + + TRACE_PATH=$(mktemp -d) + STATEDUMP_FILE=$(mktemp -u) + + # Execute test + ${TESTS[$i]} + + rm $STATEDUMP_FILE + rm -rf $TRACE_PATH + + let "i++" +done diff --git a/tests/utils/testapp/Makefile.am b/tests/utils/testapp/Makefile.am index 9bfe53666b..25d576bf6d 100644 --- a/tests/utils/testapp/Makefile.am +++ b/tests/utils/testapp/Makefile.am @@ -2,7 +2,8 @@ SUBDIRS = gen-ust-events \ gen-ust-nevents \ gen-ust-nevents-str \ gen-ust-tracef \ - gen-syscall-events + gen-syscall-events \ + gen-ust-statedump-events if HAVE_MODULES_USERSPACE_CALLSTACK_CONTEXT SUBDIRS += gen-syscall-events-callstack diff --git a/tests/utils/testapp/gen-ust-statedump-events/Makefile.am b/tests/utils/testapp/gen-ust-statedump-events/Makefile.am new file mode 100644 index 0000000000..6f74e706d9 --- /dev/null +++ b/tests/utils/testapp/gen-ust-statedump-events/Makefile.am @@ -0,0 +1,10 @@ +AM_CPPFLAGS += -I$(top_srcdir)/tests/utils -I$(srcdir) \ + -I$(top_srcdir)/tests/utils/testapp + +if HAVE_LIBLTTNG_UST_CTL +noinst_PROGRAMS = gen-ust-statedump-events +gen_ust_statedump_events_SOURCES = gen-ust-statedump-events.c tp.h +gen_ust_statedump_events_LDADD = -llttng-ust -lurcu-bp \ + $(top_builddir)/tests/utils/libtestutils.la \ + $(DL_LIBS) +endif diff --git a/tests/utils/testapp/gen-ust-statedump-events/gen-ust-statedump-events.c b/tests/utils/testapp/gen-ust-statedump-events/gen-ust-statedump-events.c new file mode 100644 index 0000000000..8d066172f9 --- /dev/null +++ b/tests/utils/testapp/gen-ust-statedump-events/gen-ust-statedump-events.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) - 2018 Geneviève Bastien + * + * 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 + */ + +#define _LGPL_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "signal-helper.h" + +#define TRACEPOINT_DEFINE +#define TRACEPOINT_CREATE_PROBES +#define TP_SESSION_CHECK +#include "../gen-ust-statedump-events/tp.h" + +static struct lttng_ust_notifier notifier; + +static void notifier_cb(struct lttng_session *session, void *priv) +{ + /* This file synchronizes with test control to make sure the statedump ran */ + char *statedump_done_file = (char *) priv; + tracepoint(tp, tpteststdmp, session, 123, "test string"); + tracepoint(tp, tpteststdmp, session, 444, "another string"); + if (statedump_done_file) { + /* Somebody may be waiting on this thread, how to tell it if + file creation went wrong? */ + create_file(statedump_done_file); + } +} + +int main(int argc, char **argv) +{ + int delay = 0; + char *initialization_file = NULL; + char *terminating_file = NULL; + char *statedump_done_file = NULL; + int ret = 0; + + if (set_signal_handler()) { + ret = -1; + goto end; + } + + if (argc >= 2) { + /* Set the application running time */ + delay = atoi(argv[1]); + } + if (argc >= 3) { + statedump_done_file = argv[2]; + } + if (argc >= 4) { + initialization_file = argv[3]; + } + if (argc >= 5) { + terminating_file = argv[4]; + } + + lttng_ust_init_statedump_notifier(¬ifier, notifier_cb, (void *) statedump_done_file); + lttng_ust_register_statedump_notifier(¬ifier); + + if (initialization_file) { + ret = create_file(initialization_file); + if (ret != 0) { + goto end; + } + } + + if (delay >= 0) { + sleep(delay); + } else if (terminating_file) { + ret = wait_on_file(terminating_file); + } else { + while (!should_quit) { + sleep(1); + } + } + + lttng_ust_unregister_statedump_notifier(¬ifier); + +end: + exit(!ret ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/tests/utils/testapp/gen-ust-statedump-events/tp.h b/tests/utils/testapp/gen-ust-statedump-events/tp.h new file mode 100644 index 0000000000..f797a96c99 --- /dev/null +++ b/tests/utils/testapp/gen-ust-statedump-events/tp.h @@ -0,0 +1,38 @@ +#undef TRACEPOINT_PROVIDER +#define TRACEPOINT_PROVIDER tp + +#if !defined(_TRACEPOINT_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ) +#define _TRACEPOINT_TP_H + +/* + * Copyright (C) 2018 Geneviève Bastien + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +#include + +TRACEPOINT_EVENT(tp, tpteststdmp, + TP_ARGS(struct lttng_session *, session, + int, value, + char *, msg), + TP_FIELDS( + ctf_integer(int64_t, myvalue, value) + ctf_string(mymsg, msg) + ) +) + +#endif /* _TRACEPOINT_TP_H */ + +#undef TRACEPOINT_INCLUDE_FILE +#define TRACEPOINT_INCLUDE_FILE ./tp.h + +/* This part must be outside ifdef protection */ +#include