From 48beefc91ce09133eac5a09bd856de83b86a54b6 Mon Sep 17 00:00:00 2001 From: Nils Carlson Date: Mon, 25 Oct 2010 12:06:31 +0200 Subject: [PATCH] Function tests for libustcmd and a C tap library This is a bunch of function tests for libustcmd, checking return values and other things and emitting output directly in TAP format. I wanted to get better feedback on what is working and what isn't and also check that functions return intelligent values. The function tests currently run without ustd. Eventually I want to link ustd into the testcase as well to check that functions return errors if no ustd instance was reachable, but right now it's enough that we get some general feedback. Signed-off-by: Nils Carlson Acked-by: David Goulet --- configure.ac | 1 + tests/Makefile.am | 13 +- tests/runtests | 2 + tests/tap.c | 173 +++++++++++++++++ tests/tap.h | 29 +++ tests/ustcmd_function_tests/Makefile.am | 10 + .../ustcmd_function_tests.c | 183 ++++++++++++++++++ 7 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 tests/tap.c create mode 100644 tests/tap.h create mode 100644 tests/ustcmd_function_tests/Makefile.am create mode 100644 tests/ustcmd_function_tests/ustcmd_function_tests.c diff --git a/configure.ac b/configure.ac index 42982c5..a9bd159 100644 --- a/configure.ac +++ b/configure.ac @@ -124,6 +124,7 @@ AC_CONFIG_FILES([ tests/trace_event/Makefile tests/tracepoint/Makefile tests/register_test/Makefile + tests/ustcmd_function_tests/Makefile libustinstr-malloc/Makefile libustfork/Makefile libustd/Makefile diff --git a/tests/Makefile.am b/tests/Makefile.am index 69801c0..526f81c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,3 +1,14 @@ -SUBDIRS = hello hello2 basic basic_long fork simple_include snprintf test-nevents test-libustinstr-malloc dlopen same_line_marker trace_event register_test tracepoint +SUBDIRS = . hello hello2 basic basic_long fork simple_include snprintf test-nevents test-libustinstr-malloc dlopen same_line_marker trace_event register_test tracepoint ustcmd_function_tests dist_noinst_SCRIPTS = test_loop runtests trace_matches + +lib_LTLIBRARIES = libtap.la + +libtap_la_SOURCES = \ + tap.c \ + tap.h + +libtap_la_LDFLAGS = -no-undefined -version-info 0:0:0 + +libtap_la_LIBADD = \ + -lpthread \ No newline at end of file diff --git a/tests/runtests b/tests/runtests index ff00253..9560c46 100755 --- a/tests/runtests +++ b/tests/runtests @@ -45,6 +45,8 @@ simple_harness_run same_line_marker/same_line_marker.sh simple_harness_run tracepoint/run +simple_harness_run ustcmd_function_tests/ustcmd_function_tests + echo "************************************" if [[ $tests_failed -eq 0 ]]; then echo "$0: All passed" diff --git a/tests/tap.c b/tests/tap.c new file mode 100644 index 0000000..940cc1a --- /dev/null +++ b/tests/tap.c @@ -0,0 +1,173 @@ +/* Copyright (C) 2010 Nils Carlson + * + * 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 +#include +#include + +static int tap_planned = -1; +static int tap_count = 1; +static int tap_passed = 0; + +static pthread_t stdout_thread; +static int pipefd[2]; +static FILE *pipe_r_file; +static FILE *normal_stdout; + +static void *_tap_comment_stdout(void *_unused) +{ + char line[4096]; + + while (fgets(&line[0], 4096, pipe_r_file)) { + if (strncmp(line, "_TAP", 4)) { + fprintf(normal_stdout, "# %s", line); + } else { + fprintf(normal_stdout, &line[4]); + } + } + pthread_exit(0); +} + +static void tap_comment_stdout(void) +{ + int stdout_fileno, new_stdout, result, fd; + + if (pipe(pipefd) < 0) { + perror("# Failed to open pipe"); + return; + } + + pipe_r_file = fdopen(pipefd[0], "r"); + if (!pipe_r_file) { + perror("# Couldn't create a FILE from the pipe"); + goto close_pipe; + } + + stdout_fileno = fileno(stdout); + if (stdout_fileno < 0) { + perror("# Couldn't get fileno for stdout!?"); + goto close_pipe_r_file; + } + + new_stdout = dup(stdout_fileno); + if (new_stdout < 0) { + perror("# Couldn't dup stdout"); + goto close_pipe_r_file; + } + + normal_stdout = fdopen(new_stdout, "w"); + if (!normal_stdout) { + perror("# Could create a FILE from new_stdout"); + goto close_dup_stdout; + } + + result = pthread_create(&stdout_thread, NULL, + _tap_comment_stdout, NULL); + if (result < 0) { + perror("# Couldn't start stdout_thread"); + goto close_normal_stdout; + } + + fclose(stdout); + fclose(stderr); + + fd = dup(pipefd[1]); + if (fd != STDOUT_FILENO) { + fprintf(stderr, "# Failed to open a new stdout!\n"); + goto close_normal_stdout; + } + + stdout = fdopen(fd, "w"); + if (!stdout) { + perror("Couldn't open a new stdout"); + goto close_fd; + } + + fd = dup(pipefd[1]); + if (fd != STDERR_FILENO) { + fprintf(stderr, "# Failed to open a new stderr!\n"); + goto close_fd; + } + + stderr = fdopen(fd, "w"); + if (!stderr) { + perror("Couldn't open a new stderr"); + goto close_fd; + } + + setlinebuf(stdout); + setlinebuf(stderr); + setlinebuf(pipe_r_file); + + return; + +close_fd: + close(fd); + +close_normal_stdout: + fclose(normal_stdout); + +close_dup_stdout: + close(new_stdout); + +close_pipe_r_file: + fclose(pipe_r_file); + +close_pipe: + close(pipefd[0]); + close(pipefd[1]); + + return; +} + +void tap_plan(int count) +{ + printf("1..%d\n", count); + + tap_count = 1; + tap_planned = count; + + tap_comment_stdout(); + +} + +int tap_status(void) +{ + if (tap_passed == tap_planned) { + return 0; + } else { + return 1; + } +} + +void tap_ok(int bool, const char *format, ...) +{ + va_list args; + char *ok_string = "_TAPok"; + char *not_ok_string = "_TAPnot ok"; + char string[4000]; + + va_start(args, format); + vsprintf(string, format, args); + va_end(args); + + printf("%s %d - %s\n", bool ? ok_string : not_ok_string, + tap_count++, string); + + if (bool) + tap_passed++; +} diff --git a/tests/tap.h b/tests/tap.h new file mode 100644 index 0000000..7cfed70 --- /dev/null +++ b/tests/tap.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2010 Nils Carlson + * + * 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 + */ +#ifndef __TAP_H +#define __TAP_H + +#include +#include + +void tap_plan(int count); + +void tap_ok(int bool, const char *format, ...); + +int tap_status(void); + +#endif /* __TAP_H */ diff --git a/tests/ustcmd_function_tests/Makefile.am b/tests/ustcmd_function_tests/Makefile.am new file mode 100644 index 0000000..b70e784 --- /dev/null +++ b/tests/ustcmd_function_tests/Makefile.am @@ -0,0 +1,10 @@ +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/tests/ + +noinst_PROGRAMS = ustcmd_function_tests +ustcmd_function_tests_SOURCES = ustcmd_function_tests.c +ustcmd_function_tests_LDADD = $(top_builddir)/libust/libust.la \ + $(top_builddir)/libustcmd/libustcmd.la \ + $(top_builddir)/libust-initializer.o \ + $(top_builddir)/tests/libtap.la \ + -lpthread + diff --git a/tests/ustcmd_function_tests/ustcmd_function_tests.c b/tests/ustcmd_function_tests/ustcmd_function_tests.c new file mode 100644 index 0000000..8a3376e --- /dev/null +++ b/tests/ustcmd_function_tests/ustcmd_function_tests.c @@ -0,0 +1,183 @@ +/* Copyright (C) 2010 Nils Carlson + * + * 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 + */ + +/* Simple function tests for ustcmd */ + +#include +#include +#include + +#include +#include + +#include "tap.h" + +static void ustcmd_function_tests(pid_t pid) +{ + int result; + unsigned int subbuf_size, subbuf_num; + unsigned int new_subbuf_size, new_subbuf_num; + struct marker_status *marker_status, *ms_ptr; + char *old_socket_path, *new_socket_path; + char *tmp_ustd_socket = "/tmp/tmp_ustd_socket"; + + printf("Connecting to pid %d\n", pid); + + /* marker status array functions */ + result = ustcmd_get_cmsf(&marker_status, pid); + tap_ok(!result, "ustcmd_get_cmsf"); + + result = 0; + for (ms_ptr = marker_status; ms_ptr->channel; ms_ptr++) { + if (!strcmp(ms_ptr->channel, "ust") && + !strcmp(ms_ptr->marker, "bar")) { + result = 1; + } + } + tap_ok(result, "Found channel \"ust\", marker \"bar\""); + + tap_ok(!ustcmd_free_cmsf(marker_status), "ustcmd_free_cmsf"); + + /* Get and set the socket path */ + tap_ok(!ustcmd_get_sock_path(&old_socket_path, pid), + "ustcmd_get_sock_path"); + + printf("Socket path: %s\n", old_socket_path); + + tap_ok(!ustcmd_set_sock_path(tmp_ustd_socket, pid), + "ustcmd_set_sock_path - set a new path"); + + tap_ok(!ustcmd_get_sock_path(&new_socket_path, pid), + "ustcmd_get_sock_path - get the new path"); + + tap_ok(!strcmp(new_socket_path, tmp_ustd_socket), + "Compare the set path and the retrieved path"); + + free(new_socket_path); + + tap_ok(!ustcmd_set_sock_path(old_socket_path, pid), + "Reset the socket path"); + + free(old_socket_path); + + /* Enable, disable markers */ + tap_ok(!ustcmd_set_marker_state("ust", "bar", 1, pid), + "ustcmd_set_marker_state - existing marker ust bar"); + + /* Create and allocate a trace */ + tap_ok(!ustcmd_create_trace(pid), "ustcmd_create_trace"); + + tap_ok(!ustcmd_alloc_trace(pid), "ustcmd_alloc_trace"); + + /* Get subbuf size and number */ + subbuf_num = ustcmd_get_subbuf_num("ust", pid); + tap_ok(subbuf_num > 0, "ustcmd_get_subbuf_num - %d sub-buffers", + subbuf_num); + + subbuf_size = ustcmd_get_subbuf_size("ust", pid); + tap_ok(subbuf_size, "ustcmd_get_subbuf_size - sub-buffer size is %d", + subbuf_size); + + /* Start the trace */ + tap_ok(!ustcmd_start_trace(pid), "ustcmd_start_trace"); + + + /* Stop the trace and destroy it*/ + tap_ok(!ustcmd_stop_trace(pid), "ustcmd_stop_trace"); + + tap_ok(!ustcmd_destroy_trace(pid), "ustcmd_destroy_trace"); + + /* Create a new trace */ + tap_ok(!ustcmd_create_trace(pid), "ustcmd_create_trace - create a new trace"); + + printf("Setting new subbufer number and sizes (doubling)\n"); + new_subbuf_num = 2 * subbuf_num; + new_subbuf_size = 2 * subbuf_size; + + tap_ok(!ustcmd_set_subbuf_num("ust", new_subbuf_num, pid), + "ustcmd_set_subbuf_num"); + + tap_ok(!ustcmd_set_subbuf_size("ust", new_subbuf_size, pid), + "ustcmd_set_subbuf_size"); + + + /* Allocate the new trace */ + tap_ok(!ustcmd_alloc_trace(pid), "ustcmd_alloc_trace - allocate the new trace"); + + + /* Get subbuf size and number and compare with what was set */ + subbuf_num = ustcmd_get_subbuf_num("ust", pid); + + subbuf_size = ustcmd_get_subbuf_size("ust", pid); + + tap_ok(subbuf_num == new_subbuf_num, "Set a new subbuf number, %d == %d", + subbuf_num, new_subbuf_num); + + + result = ustcmd_get_subbuf_size("ust", pid); + tap_ok(subbuf_size == new_subbuf_size, "Set a new subbuf size, %d == %d", + subbuf_size, new_subbuf_size); + + tap_ok(!ustcmd_destroy_trace(pid), "ustcmd_destroy_trace - without ever starting"); + + + printf("##### Tests that definetly should work are completed #####\n"); + printf("############## Start expected failure cases ##############\n"); + + tap_ok(ustcmd_set_marker_state("ust","bar", 1, pid), + "Enable already enabled marker ust/bar"); + + tap_ok(ustcmd_set_marker_state("ustl", "blar", 1, pid), + "Enable non-existent marker ustl blar"); + + tap_ok(ustcmd_start_trace(pid), + "Start a non-existent trace"); + + tap_ok(ustcmd_destroy_trace(pid), + "Destroy non-existent trace"); + + exit(tap_status() ? EXIT_FAILURE : EXIT_SUCCESS); + +} + + +int main() +{ + int i, status, pipefd[2]; + pid_t parent_pid, child_pid; + FILE *pipe_file; + + tap_plan(27); + + printf("Function tests for ustcmd\n"); + + parent_pid = getpid(); + child_pid = fork(); + if (child_pid) { + for(i=0; i<10; i++) { + trace_mark(ust, bar, "str %s", "FOOBAZ"); + trace_mark(ust, bar2, "number1 %d number2 %d", 53, 9800); + usleep(100000); + } + + wait(&status); + } else { + ustcmd_function_tests(parent_pid); + } + + exit(status ? EXIT_FAILURE : EXIT_SUCCESS); +} -- 2.34.1