From 37bd6c8e4c4a3d7054d97627e4fb4bef1d4612a6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Mon, 25 Mar 2013 20:28:34 -0400 Subject: [PATCH] Tests: Add "fork" ust regression test MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Based on the "fork" test formerly part of lttng-ust. Signed-off-by: Jérémie Galarneau Signed-off-by: David Goulet --- .gitignore | 2 + configure.ac | 1 + tests/fast_regression | 1 + tests/long_regression | 1 + tests/regression/ust/Makefile.am | 2 +- tests/regression/ust/fork/Makefile.am | 20 ++++ tests/regression/ust/fork/README | 26 +++++ tests/regression/ust/fork/fork.c | 62 +++++++++++ tests/regression/ust/fork/fork2.c | 32 ++++++ tests/regression/ust/fork/test_fork | 35 ++++++ tests/regression/ust/fork/test_fork.py | 124 +++++++++++++++++++++ tests/regression/ust/fork/ust_tests_fork.h | 66 +++++++++++ 12 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 tests/regression/ust/fork/Makefile.am create mode 100644 tests/regression/ust/fork/README create mode 100644 tests/regression/ust/fork/fork.c create mode 100644 tests/regression/ust/fork/fork2.c create mode 100755 tests/regression/ust/fork/test_fork create mode 100644 tests/regression/ust/fork/test_fork.py create mode 100644 tests/regression/ust/fork/ust_tests_fork.h diff --git a/.gitignore b/.gitignore index 4c186d2e4..533973aa1 100644 --- a/.gitignore +++ b/.gitignore @@ -69,5 +69,7 @@ tests/regression/ust/linking/demo_static tests/regression/ust/linking/demo tests/regression/ust/daemon/daemon tests/regression/ust/exit-fast/exit-fast +tests/regression/ust/fork/fork +tests/regression/ust/fork/fork2 benchmark/ diff --git a/configure.ac b/configure.ac index 88d8a33af..d7ca25371 100644 --- a/configure.ac +++ b/configure.ac @@ -335,6 +335,7 @@ AC_CONFIG_FILES([ tests/regression/ust/linking/Makefile tests/regression/ust/daemon/Makefile tests/regression/ust/exit-fast/Makefile + tests/regression/ust/fork/Makefile tests/unit/Makefile tests/utils/Makefile tests/utils/tap/Makefile diff --git a/tests/fast_regression b/tests/fast_regression index e5886615b..cc561fb55 100644 --- a/tests/fast_regression +++ b/tests/fast_regression @@ -15,3 +15,4 @@ regression/ust/test_event_wildcard regression/ust/linking/test_linking regression/ust/daemon/test_daemon regression/ust/exit-fast/test_exit-fast +regression/ust/fork/test_fork diff --git a/tests/long_regression b/tests/long_regression index a81d094cd..810b661db 100644 --- a/tests/long_regression +++ b/tests/long_regression @@ -17,3 +17,4 @@ regression/ust/test_event_wildcard regression/ust/linking/test_linking regression/ust/daemon/test_daemon regression/ust/exit-fast/test_exit-fast +regression/ust/fork/test_fork diff --git a/tests/regression/ust/Makefile.am b/tests/regression/ust/Makefile.am index 1631ba66c..23613bdeb 100644 --- a/tests/regression/ust/Makefile.am +++ b/tests/regression/ust/Makefile.am @@ -1,6 +1,6 @@ if HAVE_LIBLTTNG_UST_CTL SUBDIRS = nprocesses high-throughput low-throughput before-after multi-session \ - overlap buffers-uid linking daemon exit-fast + overlap buffers-uid linking daemon exit-fast fork EXTRA_DIST = test_event_basic test_event_wildcard diff --git a/tests/regression/ust/fork/Makefile.am b/tests/regression/ust/fork/Makefile.am new file mode 100644 index 000000000..97f134f79 --- /dev/null +++ b/tests/regression/ust/fork/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = -I$(srcdir) + +noinst_PROGRAMS = fork fork2 +fork_SOURCES = fork.c ust_tests_fork.h +fork_LDADD = -llttng-ust -llttng-ust-fork + +fork2_SOURCES = fork2.c +fork2_LDADD = -llttng-ust -llttng-ust-fork + +if LTTNG_TOOLS_BUILD_WITH_LIBDL +fork_LDADD += -ldl +fork2_LDADD += -ldl +endif +if LTTNG_TOOLS_BUILD_WITH_LIBC_DL +fork_LDADD += -lc +fork2_LDADD += -lc +endif + +noinst_SCRIPTS = test_fork test_fork.py +EXTRA_DIST = test_fork test_fork.py diff --git a/tests/regression/ust/fork/README b/tests/regression/ust/fork/README new file mode 100644 index 000000000..eb36100f7 --- /dev/null +++ b/tests/regression/ust/fork/README @@ -0,0 +1,26 @@ +Fork tracing test +------------------- + +This test checks if tracing works correctly in a child process created by a +fork() call, as well as after an exec() call. + +DESCRIPTION +----------- + +The test_fork script launches a binary that forks and calls exec() with +the command provided as the argument. Tracepoints are placed before and +after these calls to verify tracing remains operational at all times. + +The binary loaded as the new process image also logs an event. + +The resulting trace is parsed to make sure the every event was logged +successfully with the correct PIDs. + +DEPENDENCIES +------------ + +To run this test, you will need: + + - lttng-tools (with python bindings) + - babeltrace + - python 3.0 or better diff --git a/tests/regression/ust/fork/fork.c b/tests/regression/ust/fork/fork.c new file mode 100644 index 000000000..744e9203e --- /dev/null +++ b/tests/regression/ust/fork/fork.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 Pierre-Marc Fournier + * Copyright (C) 2011 Mathieu Desnoyers + * + * 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 + */ + +#include +#include +#include +#include + +#define TRACEPOINT_DEFINE +#define TRACEPOINT_CREATE_PROBES +#include "ust_tests_fork.h" + +int main(int argc, char **argv, char *env[]) +{ + int result; + + if (argc < 2) { + fprintf(stderr, "usage: fork PROG_TO_EXEC\n"); + exit(1); + } + + printf("parent_pid %d\n", getpid()); + tracepoint(ust_tests_fork, before_fork, getpid()); + + result = fork(); + if (result == -1) { + perror("fork"); + return 1; + } + if (result == 0) { + char *args[] = { "fork2", NULL }; + + tracepoint(ust_tests_fork, after_fork_child, getpid()); + + result = execve(argv[1], args, env); + if (result == -1) { + perror("execve"); + return 1; + } + } else { + printf("child_pid %d\n", result); + tracepoint(ust_tests_fork, after_fork_parent, getpid()); + } + + return 0; +} diff --git a/tests/regression/ust/fork/fork2.c b/tests/regression/ust/fork/fork2.c new file mode 100644 index 000000000..ee0f36b20 --- /dev/null +++ b/tests/regression/ust/fork/fork2.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2009 Pierre-Marc Fournier + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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 + */ + +#include +#include + +#define TRACEPOINT_DEFINE +#define TRACEPOINT_CREATE_PROBES +#include "ust_tests_fork.h" + +int main() +{ + printf("IN FORK2\n"); + + tracepoint(ust_tests_fork, after_exec, getpid()); + + return 0; +} diff --git a/tests/regression/ust/fork/test_fork b/tests/regression/ust/fork/test_fork new file mode 100755 index 000000000..e05b5560d --- /dev/null +++ b/tests/regression/ust/fork/test_fork @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright (C) - 2013 Jérémie Galarneau +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License, version 2 only, as +# published by the Free Software Foundation. +# +# This program 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 General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Check for a running sessiond +`pidof lt-lttng-sessiond` +STOP_SESSIOND=$? + +CURDIR=$(dirname $0) +TESTDIR=${CURDIR}/../../.. + +# Try to launch a sessiond before invoking the python test script +if [ $STOP_SESSIOND -ne 0 ]; then + DIR=$(readlink -f ${TESTDIR}) + ${DIR}/../src/bin/lttng-sessiond/lttng-sessiond --daemonize --quiet --consumerd32-path="$DIR/../src/bin/lttng-consumerd/lttng-consumerd" --consumerd64-path="$DIR/../src/bin/lttng-consumerd/lttng-consumerd" +fi + +python3 ${CURDIR}/test_fork.py + +if [ $STOP_SESSIOND -ne 0 ]; then + kill `pidof lt-lttng-sessiond` +fi diff --git a/tests/regression/ust/fork/test_fork.py b/tests/regression/ust/fork/test_fork.py new file mode 100644 index 000000000..62faf71f1 --- /dev/null +++ b/tests/regression/ust/fork/test_fork.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# +# Copyright (C) - 2013 Jérémie Galarneau +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License, version 2 only, as +# published by the Free Software Foundation. +# +# This program 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 General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os +import subprocess +import re +import shutil +import sys + +test_path = os.path.dirname(os.path.abspath(__file__)) + "/" +test_utils_path = test_path +for i in range(4): + test_utils_path = os.path.dirname(test_utils_path) +test_utils_path = test_utils_path + "/utils" +sys.path.append(test_utils_path) +from test_utils import * + + +NR_TESTS = 6 +current_test = 1 +print("1..{0}".format(NR_TESTS)) + +# Check if a sessiond is running... bail out if none found. +if session_daemon_alive() == 0: + bail("No sessiond running. Please make sure you are running this test with the \"run\" shell script and verify that the lttng tools are properly installed.") + +session_info = create_session() +enable_ust_tracepoint_event(session_info, "ust_tests_fork*") +start_session(session_info) + +fork_process = subprocess.Popen([test_path + "fork", test_path + "fork2"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + +if sys.version_info >= (3, 3): + try: + fork_process.wait(5) + except TimeoutExpired: + fork_process.kill() + bail("Failed to run fork test application (time out)", session_info) +else: + fork_process.wait() + +parent_pid = -1 +child_pid = -1 +for line in fork_process.stdout: + line = line.decode('utf-8').replace("\n", "") + match = re.search(r"child_pid (\d+)", line) + if match: + child_pid = match.group(1) + match = re.search(r"parent_pid (\d+)", line) + if match: + parent_pid = match.group(1) + +print_test_result(fork_process.returncode == 0, current_test, "Fork test application exited normally") +current_test += 1 + +stop_session(session_info) + +# Check both events (normal exit and suicide messages) are present in the resulting trace +try: + babeltrace_process = subprocess.Popen(["babeltrace", session_info.trace_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) +except FileNotFoundError: + bail("Could not open babeltrace. Please make sure it is installed.", session_info) + +event_lines = [] +for event_line in babeltrace_process.stdout: + event_line = event_line.decode('utf-8').replace("\n", "") + if re.search(r"warning", event_line) is not None or re.search(r"error", event_line) is not None: + print( "# " + event_line ) + else: + event_lines.append(event_line) + +babeltrace_process.wait() + +print_test_result(babeltrace_process.returncode == 0, current_test, "Resulting trace is readable") +current_test += 1 + +if babeltrace_process.returncode != 0: + bail("Unreadable trace; can't proceed with analysis.", session_info) + +event_before_fork = False +event_after_fork_parent = False +event_after_fork_child = False +event_after_exec = False + +for event_line in event_lines: + match = re.search(r".*pid = (\d+)", event_line) + if match is not None: + event_pid = match.group(1) + else: + continue + + if re.search(r"before_fork", event_line): + event_before_fork = (event_pid == parent_pid) + if re.search(r"after_fork_parent", event_line): + event_after_fork_parent = (event_pid == parent_pid) + if re.search(r"after_fork_child", event_line): + event_after_fork_child = (event_pid == child_pid) + if re.search(r"after_exec", event_line): + event_after_exec = (event_pid == child_pid) + +print_test_result(event_before_fork, current_test, "before_fork event logged by parent process found in trace") +current_test += 1 +print_test_result(event_after_fork_parent, current_test, "after_fork_parent event logged by parent process found in trace") +current_test += 1 +print_test_result(event_after_fork_child, current_test, "after_fork_child event logged by child process found in trace") +current_test += 1 +print_test_result(event_after_exec, current_test, "after_exec event logged by child process found in trace") +current_test += 1 + +shutil.rmtree(session_info.tmp_directory) diff --git a/tests/regression/ust/fork/ust_tests_fork.h b/tests/regression/ust/fork/ust_tests_fork.h new file mode 100644 index 000000000..b034f9fab --- /dev/null +++ b/tests/regression/ust/fork/ust_tests_fork.h @@ -0,0 +1,66 @@ +#undef TRACEPOINT_PROVIDER +#define TRACEPOINT_PROVIDER ust_tests_fork + +#if !defined(_TRACEPOINT_UST_TESTS_FORK_H) || defined(TRACEPOINT_HEADER_MULTI_READ) +#define _TRACEPOINT_UST_TESTS_FORK_H + +/* + * Copyright (C) 2011 Mathieu Desnoyers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +TRACEPOINT_EVENT(ust_tests_fork, before_fork, + TP_ARGS(pid_t, pid), + TP_FIELDS( + ctf_integer(pid_t, pid, pid) + ) +) + +TRACEPOINT_EVENT(ust_tests_fork, after_fork_child, + TP_ARGS(pid_t, pid), + TP_FIELDS( + ctf_integer(pid_t, pid, pid) + ) +) + +TRACEPOINT_EVENT(ust_tests_fork, after_fork_parent, + TP_ARGS(pid_t, pid), + TP_FIELDS( + ctf_integer(pid_t, pid, pid) + ) +) + +TRACEPOINT_EVENT(ust_tests_fork, after_exec, + TP_ARGS(pid_t, pid), + TP_FIELDS( + ctf_integer(pid_t, pid, pid) + ) +) + +#endif /* _TRACEPOINT_UST_TESTS_FORK_H */ + +#undef TRACEPOINT_INCLUDE +#define TRACEPOINT_INCLUDE "./ust_tests_fork.h" + +/* This part must be outside ifdef protection */ +#include -- 2.34.1