#include <common/macros.h>
#include <common/payload-view.h>
#include <lttng/action/rate-policy.h>
+#include <lttng/lttng-error.h>
#include <stdbool.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct mi_writer;
int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy,
const struct lttng_rate_policy *policy,
struct mi_writer *writer);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* LTTNG_RATE_POLICY */
#include <common/macros.h>
#include <lttng/event-expr.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct lttng_bytecode;
struct mi_writer;
const struct lttng_event_expr *expression,
struct mi_writer *writer);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* LTTNG_EVENT_EXPR_INTERNAL_H */
#include <common/fd-handle.h>
#include <common/macros.h>
#include <lttng/kernel-probe.h>
+#include <lttng/lttng-error.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct lttng_payload;
struct lttng_payload_view;
struct lttng_dynamic_buffer;
const struct lttng_kernel_probe_location *location,
struct mi_writer *writer);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* LTTNG_KERNEL_PROBE_INTERNAL_H */
#include <common/payload.h>
#include <lttng/event.h>
#include <lttng/log-level-rule.h>
+#include <lttng/lttng-error.h>
#ifdef __cplusplus
extern "C" {
utils.h
noinst_PROGRAMS = filter-grammar-test
-filter_grammar_test_SOURCES = filter-grammar-test.c
+filter_grammar_test_SOURCES = filter-grammar-test.cpp
filter_grammar_test_LDADD = \
libcommon.la
noinst_LTLIBRARIES = libcompat.la
-libcompat_la_SOURCES = poll.c poll.h fcntl.h endian.h mman.h dirent.h \
- socket.h compat-fcntl.c tid.h \
- getenv.h string.h paths.h pthread.h netdb.h \
- time.h directory-handle.h directory-handle.c path.h \
- errno.h
+libcompat_la_SOURCES = \
+ compat-fcntl.cpp \
+ directory-handle.cpp \
+ directory-handle.h \
+ dirent.h \
+ endian.h \
+ errno.h \
+ fcntl.h \
+ getenv.h \
+ mman.h \
+ netdb.h \
+ path.h \
+ paths.h \
+ poll.cpp \
+ poll.h \
+ pthread.h \
+ socket.h \
+ string.h \
+ tid.h \
+ time.h
+++ /dev/null
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <common/compat/fcntl.h>
-#include <common/macros.h>
-#include <unistd.h>
-
-#ifdef __linux__
-
-int compat_sync_file_range(int fd, off64_t offset, off64_t nbytes,
- unsigned int flags)
-{
-#ifdef HAVE_SYNC_FILE_RANGE
- return sync_file_range(fd, offset, nbytes, flags);
-#else
- return fdatasync(fd);
-#endif
-}
-
-#endif /* __linux__ */
--- /dev/null
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <common/compat/fcntl.h>
+#include <common/macros.h>
+#include <unistd.h>
+
+#ifdef __linux__
+
+int compat_sync_file_range(int fd, off64_t offset, off64_t nbytes,
+ unsigned int flags)
+{
+#ifdef HAVE_SYNC_FILE_RANGE
+ return sync_file_range(fd, offset, nbytes, flags);
+#else
+ return fdatasync(fd);
+#endif
+}
+
+#endif /* __linux__ */
+++ /dev/null
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <common/compat/directory-handle.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/runas.h>
-#include <common/credentials.h>
-#include <lttng/constant.h>
-#include <common/dynamic-array.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <dirent.h>
-
-/*
- * This compatibility layer shares a common "base" that is implemented
- * in terms of an internal API. This file contains two implementations
- * of the internal API below.
- */
-static
-int lttng_directory_handle_mkdir(
- const struct lttng_directory_handle *handle,
- const char *path, mode_t mode);
-static
-int _run_as_mkdir(const struct lttng_directory_handle *handle, const char *path,
- mode_t mode, uid_t uid, gid_t gid);
-static
-int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
- const char *path, mode_t mode, uid_t uid, gid_t gid);
-static
-int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
- const char *filename, int flags, mode_t mode);
-static
-int _run_as_open(const struct lttng_directory_handle *handle,
- const char *filename,
- int flags, mode_t mode, uid_t uid, gid_t gid);
-static
-int lttng_directory_handle_unlink(
- const struct lttng_directory_handle *handle,
- const char *filename);
-static
-int _run_as_unlink(const struct lttng_directory_handle *handle,
- const char *filename, uid_t uid, gid_t gid);
-static
-int _lttng_directory_handle_rename(
- const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name);
-static
-int _run_as_rename(const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name, uid_t uid, gid_t gid);
-static
-DIR *lttng_directory_handle_opendir(const struct lttng_directory_handle *handle,
- const char *path);
-static
-int lttng_directory_handle_rmdir(
- const struct lttng_directory_handle *handle, const char *name);
-static
-int _run_as_rmdir(const struct lttng_directory_handle *handle,
- const char *name, uid_t uid, gid_t gid);
-static
-int _run_as_rmdir_recursive(
- const struct lttng_directory_handle *handle, const char *name,
- uid_t uid, gid_t gid, int flags);
-static
-void lttng_directory_handle_invalidate(struct lttng_directory_handle *handle);
-static
-void lttng_directory_handle_release(struct urcu_ref *ref);
-
-#ifdef HAVE_DIRFD
-
-/*
- * Special inode number reserved to represent the "current working directory".
- * ino_t is spec'ed as being an unsigned integral type.
- */
-#define RESERVED_AT_FDCWD_INO \
- ({ \
- uint64_t reserved_val; \
- switch (sizeof(ino_t)) { \
- case 4: \
- reserved_val = UINT32_MAX; \
- break; \
- case 8: \
- reserved_val = UINT64_MAX; \
- break; \
- default: \
- abort(); \
- } \
- (ino_t) reserved_val; \
- })
-
-struct lttng_directory_handle *lttng_directory_handle_create(const char *path)
-{
- const struct lttng_directory_handle cwd_handle = {
- .dirfd = AT_FDCWD,
- };
-
- /* Open a handle to the CWD if NULL is passed. */
- return lttng_directory_handle_create_from_handle(path, &cwd_handle);
-}
-
-struct lttng_directory_handle *lttng_directory_handle_create_from_handle(
- const char *path,
- const struct lttng_directory_handle *ref_handle)
-{
- int dirfd;
- struct lttng_directory_handle *handle = NULL;
-
- if (!path) {
- handle = lttng_directory_handle_copy(ref_handle);
- goto end;
- }
- if (!*path) {
- ERR("Failed to initialize directory handle: provided path is an empty string");
- goto end;
- }
-
- dirfd = openat(ref_handle->dirfd, path, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
- if (dirfd == -1) {
- PERROR("Failed to initialize directory handle to \"%s\"", path);
- goto end;
- }
-
- handle = lttng_directory_handle_create_from_dirfd(dirfd);
- if (!handle) {
- goto error_close;
- }
-end:
- return handle;
-error_close:
- if (close(dirfd)) {
- PERROR("Failed to close directory file descriptor");
- }
- return NULL;
-}
-
-struct lttng_directory_handle *lttng_directory_handle_create_from_dirfd(
- int dirfd)
-{
- int ret;
- struct lttng_directory_handle *handle = zmalloc(sizeof(*handle));
- struct stat stat_buf;
-
- if (!handle) {
- goto end;
- }
-
- if (dirfd != AT_FDCWD) {
- ret = fstat(dirfd, &stat_buf);
- if (ret) {
- PERROR("Failed to fstat directory file descriptor %i", dirfd);
- lttng_directory_handle_release(&handle->ref);
- handle = NULL;
- goto end;
- }
- } else {
- handle->directory_inode = RESERVED_AT_FDCWD_INO;
- }
- handle->dirfd = dirfd;
- urcu_ref_init(&handle->ref);
-end:
- return handle;
-}
-
-static
-void lttng_directory_handle_release(struct urcu_ref *ref)
-{
- int ret;
- struct lttng_directory_handle *handle =
- container_of(ref, struct lttng_directory_handle, ref);
-
- if (handle->destroy_cb) {
- handle->destroy_cb(handle, handle->destroy_cb_data);
- }
-
- if (handle->dirfd == AT_FDCWD || handle->dirfd == -1) {
- goto end;
- }
- ret = close(handle->dirfd);
- if (ret == -1) {
- PERROR("Failed to close directory file descriptor of directory handle");
- }
-end:
- lttng_directory_handle_invalidate(handle);
- free(handle);
-}
-
-struct lttng_directory_handle *lttng_directory_handle_copy(
- const struct lttng_directory_handle *handle)
-{
- struct lttng_directory_handle *new_handle = NULL;
-
- if (handle->dirfd == AT_FDCWD) {
- new_handle = lttng_directory_handle_create_from_dirfd(AT_FDCWD);
- } else {
- const int new_dirfd = dup(handle->dirfd);
-
- if (new_dirfd == -1) {
- PERROR("Failed to duplicate directory file descriptor of directory handle");
- goto end;
- }
- new_handle = lttng_directory_handle_create_from_dirfd(
- new_dirfd);
- if (!new_handle && close(new_dirfd)) {
- PERROR("Failed to close directory file descriptor of directory handle");
- }
- }
-end:
- return new_handle;
-}
-
-bool lttng_directory_handle_equals(const struct lttng_directory_handle *lhs,
- const struct lttng_directory_handle *rhs)
-{
- return lhs->directory_inode == rhs->directory_inode;
-}
-
-static
-void lttng_directory_handle_invalidate(struct lttng_directory_handle *handle)
-{
- handle->dirfd = -1;
-}
-
-int lttng_directory_handle_stat(const struct lttng_directory_handle *handle,
- const char *path, struct stat *st)
-{
- return fstatat(handle->dirfd, path, st, 0);
-}
-
-bool lttng_directory_handle_uses_fd(
- const struct lttng_directory_handle *handle)
-{
- return handle->dirfd != AT_FDCWD;
-}
-
-static
-int lttng_directory_handle_mkdir(
- const struct lttng_directory_handle *handle,
- const char *path, mode_t mode)
-{
- return mkdirat(handle->dirfd, path, mode);
-}
-
-static
-int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
- const char *filename, int flags, mode_t mode)
-{
- return openat(handle->dirfd, filename, flags, mode);
-}
-
-static
-int _run_as_open(const struct lttng_directory_handle *handle,
- const char *filename,
- int flags, mode_t mode, uid_t uid, gid_t gid)
-{
- return run_as_openat(handle->dirfd, filename, flags, mode, uid, gid);
-}
-
-static
-int _run_as_unlink(const struct lttng_directory_handle *handle,
- const char *filename, uid_t uid, gid_t gid)
-{
- return run_as_unlinkat(handle->dirfd, filename, uid, gid);
-}
-
-static
-int lttng_directory_handle_unlink(
- const struct lttng_directory_handle *handle,
- const char *filename)
-{
- return unlinkat(handle->dirfd, filename, 0);
-}
-
-static
-int _run_as_mkdir(const struct lttng_directory_handle *handle,
- const char *path, mode_t mode, uid_t uid, gid_t gid)
-{
- return run_as_mkdirat(handle->dirfd, path, mode, uid, gid);
-}
-
-static
-int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
- const char *path, mode_t mode, uid_t uid, gid_t gid)
-{
- return run_as_mkdirat_recursive(handle->dirfd, path, mode, uid, gid);
-}
-
-static
-int _lttng_directory_handle_rename(
- const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name)
-{
- return renameat(old_handle->dirfd, old_name,
- new_handle->dirfd, new_name);
-}
-
-static
-int _run_as_rename(const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name, uid_t uid, gid_t gid)
-{
- return run_as_renameat(old_handle->dirfd, old_name, new_handle->dirfd,
- new_name, uid, gid);
-}
-
-static
-DIR *lttng_directory_handle_opendir(const struct lttng_directory_handle *handle,
- const char *path)
-{
- DIR *dir_stream = NULL;
- int fd = openat(handle->dirfd, path, O_RDONLY);
-
- if (fd < 0) {
- goto end;
- }
-
- dir_stream = fdopendir(fd);
- if (!dir_stream) {
- int ret;
-
- PERROR("Failed to open directory stream");
- ret = close(fd);
- if (ret) {
- PERROR("Failed to close file descriptor to %s", path);
- }
- goto end;
- }
-
-end:
- return dir_stream;
-}
-
-static
-int lttng_directory_handle_rmdir(
- const struct lttng_directory_handle *handle, const char *name)
-{
- int ret = unlinkat(handle->dirfd, name, AT_REMOVEDIR);
- if (ret) {
- PERROR("Failed to remove directory `%s`", name);
- }
-
- return ret;
-}
-
-static
-int _run_as_rmdir(const struct lttng_directory_handle *handle,
- const char *name, uid_t uid, gid_t gid)
-{
- return run_as_rmdirat(handle->dirfd, name, uid, gid);
-}
-
-static
-int _run_as_rmdir_recursive(
- const struct lttng_directory_handle *handle, const char *name,
- uid_t uid, gid_t gid, int flags)
-{
- return run_as_rmdirat_recursive(handle->dirfd, name, uid, gid, flags);
-}
-
-#else /* HAVE_DIRFD */
-
-static
-int get_full_path(const struct lttng_directory_handle *handle,
- const char *subdirectory, char *fullpath, size_t size)
-{
- int ret;
- const bool subdirectory_is_absolute =
- subdirectory && *subdirectory == '/';
- const char * const base = subdirectory_is_absolute ?
- subdirectory : handle->base_path;
- const char * const end = subdirectory && !subdirectory_is_absolute ?
- subdirectory : NULL;
- const size_t base_len = strlen(base);
- const size_t end_len = end ? strlen(end) : 0;
- const bool add_separator_slash = end && base[base_len - 1] != '/';
- const bool add_trailing_slash = end && end[end_len - 1] != '/';
-
- ret = snprintf(fullpath, size, "%s%s%s%s",
- base,
- add_separator_slash ? "/" : "",
- end ? end : "",
- add_trailing_slash ? "/" : "");
- if (ret == -1 || ret >= size) {
- ERR("Failed to format subdirectory from directory handle");
- ret = -1;
- goto end;
- }
- ret = 0;
-end:
- return ret;
-}
-
-static
-struct lttng_directory_handle *_lttng_directory_handle_create(char *path)
-{
- struct lttng_directory_handle *handle = zmalloc(sizeof(*handle));
-
- if (!handle) {
- goto end;
- }
- urcu_ref_init(&handle->ref);
- handle->base_path = path;
-end:
- return handle;
-}
-
-struct lttng_directory_handle *lttng_directory_handle_create(
- const char *path)
-{
- int ret;
- const char *cwd = "";
- size_t cwd_len, path_len;
- char cwd_buf[LTTNG_PATH_MAX] = {};
- char handle_buf[LTTNG_PATH_MAX] = {};
- struct lttng_directory_handle *new_handle = NULL;
- bool add_cwd_slash = false, add_trailing_slash = false;
- const struct lttng_directory_handle cwd_handle = {
- .base_path = handle_buf,
- };
-
- path_len = path ? strlen(path) : 0;
- add_trailing_slash = path && path[path_len - 1] != '/';
- if (!path || (path && *path != '/')) {
- cwd = getcwd(cwd_buf, sizeof(cwd_buf));
- if (!cwd) {
- PERROR("Failed to initialize directory handle, can't get current working directory");
- ret = -1;
- goto end;
- }
- cwd_len = strlen(cwd);
- if (cwd_len == 0) {
- ERR("Failed to initialize directory handle, current working directory path has a length of 0");
- ret = -1;
- goto end;
- }
- add_cwd_slash = cwd[cwd_len - 1] != '/';
- }
-
- ret = snprintf(handle_buf, sizeof(handle_buf), "%s%s%s%s",
- cwd,
- add_cwd_slash ? "/" : "",
- path ? : "",
- add_trailing_slash ? "/" : "");
- if (ret == -1 || ret >= LTTNG_PATH_MAX) {
- ERR("Failed to initialize directory handle, failed to format directory path");
- goto end;
- }
-
- new_handle = lttng_directory_handle_create_from_handle(path, &cwd_handle);
-end:
- return new_handle;
-}
-
-struct lttng_directory_handle *lttng_directory_handle_create_from_handle(
- const char *path,
- const struct lttng_directory_handle *ref_handle)
-{
- int ret;
- size_t path_len, handle_path_len;
- bool add_trailing_slash;
- struct stat stat_buf;
- struct lttng_directory_handle *new_handle = NULL;
- char *new_path = NULL;
-
- LTTNG_ASSERT(ref_handle && ref_handle->base_path);
-
- ret = lttng_directory_handle_stat(ref_handle, path, &stat_buf);
- if (ret == -1) {
- PERROR("Failed to create directory handle");
- goto end;
- } else if (!S_ISDIR(stat_buf.st_mode)) {
- char full_path[LTTNG_PATH_MAX];
-
- /* Best effort for logging purposes. */
- ret = get_full_path(ref_handle, path, full_path,
- sizeof(full_path));
- if (ret) {
- full_path[0] = '\0';
- }
-
- ERR("Failed to initialize directory handle to \"%s\": not a directory",
- full_path);
- goto end;
- }
- if (!path) {
- new_handle = lttng_directory_handle_copy(ref_handle);
- goto end;
- }
-
- path_len = strlen(path);
- if (path_len == 0) {
- ERR("Failed to initialize directory handle: provided path is an empty string");
- ret = -1;
- goto end;
- }
- if (*path == '/') {
- new_path = strdup(path);
- if (!new_path) {
- goto end;
- }
- /* Takes ownership of new_path. */
- new_handle = _lttng_directory_handle_create(new_path);
- new_path = NULL;
- goto end;
- }
-
- add_trailing_slash = path[path_len - 1] != '/';
-
- handle_path_len = strlen(ref_handle->base_path) + path_len +
- !!add_trailing_slash;
- if (handle_path_len >= LTTNG_PATH_MAX) {
- ERR("Failed to initialize directory handle as the resulting path's length (%zu bytes) exceeds the maximal allowed length (%d bytes)",
- handle_path_len, LTTNG_PATH_MAX);
- goto end;
- }
- new_path = zmalloc(handle_path_len);
- if (!new_path) {
- PERROR("Failed to initialize directory handle");
- goto end;
- }
-
- ret = sprintf(new_handle->base_path, "%s%s%s",
- ref_handle->base_path,
- path,
- add_trailing_slash ? "/" : "");
- if (ret == -1 || ret >= handle_path_len) {
- ERR("Failed to initialize directory handle: path formatting failed");
- goto end;
- }
- new_handle = _lttng_directory_handle_create(new_path);
- new_path = NULL;
-end:
- free(new_path);
- return new_handle;
-}
-
-struct lttng_directory_handle *lttng_directory_handle_create_from_dirfd(
- int dirfd)
-{
- LTTNG_ASSERT(dirfd == AT_FDCWD);
- return lttng_directory_handle_create(NULL);
-}
-
-static
-void lttng_directory_handle_release(struct urcu_ref *ref)
-{
- struct lttng_directory_handle *handle =
- container_of(ref, struct lttng_directory_handle, ref);
-
- free(handle->base_path);
- lttng_directory_handle_invalidate(handle);
- free(handle);
-}
-
-struct lttng_directory_handle *lttng_directory_handle_copy(
- const struct lttng_directory_handle *handle)
-{
- struct lttng_directory_handle *new_handle = NULL;
- char *new_path = NULL;
-
- if (handle->base_path) {
- new_path = strdup(handle->base_path);
- if (!new_path) {
- goto end;
- }
- }
- new_handle = _lttng_directory_handle_create(new_path);
-end:
- return new_handle;
-}
-
-bool lttng_directory_handle_equals(const struct lttng_directory_handle *lhs,
- const struct lttng_directory_handle *rhs)
-{
- return strcmp(lhs->base_path, rhs->base_path) == 0;
-}
-
-static
-void lttng_directory_handle_invalidate(struct lttng_directory_handle *handle)
-{
- handle->base_path = NULL;
-}
-
-int lttng_directory_handle_stat(const struct lttng_directory_handle *handle,
- const char *subdirectory, struct stat *st)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, subdirectory, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = stat(fullpath, st);
-end:
- return ret;
-}
-
-bool lttng_directory_handle_uses_fd(
- const struct lttng_directory_handle *handle)
-{
- return false;
-}
-
-static
-int lttng_directory_handle_mkdir(const struct lttng_directory_handle *handle,
- const char *subdirectory, mode_t mode)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, subdirectory, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = mkdir(fullpath, mode);
-end:
- return ret;
-}
-
-static
-int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
- const char *filename, int flags, mode_t mode)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = open(fullpath, flags, mode);
-end:
- return ret;
-}
-
-static
-int lttng_directory_handle_unlink(
- const struct lttng_directory_handle *handle,
- const char *filename)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = unlink(fullpath);
-end:
- return ret;
-}
-
-static
-int _run_as_mkdir(const struct lttng_directory_handle *handle, const char *path,
- mode_t mode, uid_t uid, gid_t gid)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, path, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = run_as_mkdir(fullpath, mode, uid, gid);
-end:
- return ret;
-}
-
-static
-int _run_as_open(const struct lttng_directory_handle *handle,
- const char *filename,
- int flags, mode_t mode, uid_t uid, gid_t gid)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = run_as_open(fullpath, flags, mode, uid, gid);
-end:
- return ret;
-}
-
-static
-int _run_as_unlink(const struct lttng_directory_handle *handle,
- const char *filename, uid_t uid, gid_t gid)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = run_as_unlink(fullpath, uid, gid);
-end:
- return ret;
-}
-
-static
-int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
- const char *path, mode_t mode, uid_t uid, gid_t gid)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, path, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = run_as_mkdir_recursive(fullpath, mode, uid, gid);
-end:
- return ret;
-}
-
-static
-int _lttng_directory_handle_rename(
- const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name)
-{
- int ret;
- char old_fullpath[LTTNG_PATH_MAX];
- char new_fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(old_handle, old_name, old_fullpath,
- sizeof(old_fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
- ret = get_full_path(new_handle, new_name, new_fullpath,
- sizeof(new_fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = rename(old_fullpath, new_fullpath);
-end:
- return ret;
-}
-
-static
-int _run_as_rename(const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name, uid_t uid, gid_t gid)
-{
- int ret;
- char old_fullpath[LTTNG_PATH_MAX];
- char new_fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(old_handle, old_name, old_fullpath,
- sizeof(old_fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
- ret = get_full_path(new_handle, new_name, new_fullpath,
- sizeof(new_fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = run_as_rename(old_fullpath, new_fullpath, uid, gid);
-end:
- return ret;
-}
-
-static
-DIR *lttng_directory_handle_opendir(const struct lttng_directory_handle *handle,
- const char *path)
-{
- int ret;
- DIR *dir_stream = NULL;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, path, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- dir_stream = opendir(fullpath);
-end:
- return dir_stream;
-}
-
-static
-int lttng_directory_handle_rmdir(
- const struct lttng_directory_handle *handle, const char *name)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, name, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = rmdir(fullpath);
-end:
- return ret;
-}
-
-static
-int _run_as_rmdir(const struct lttng_directory_handle *handle,
- const char *name, uid_t uid, gid_t gid)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, name, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = run_as_rmdir(fullpath, uid, gid);
-end:
- return ret;
-}
-
-static
-int _run_as_rmdir_recursive(
- const struct lttng_directory_handle *handle, const char *name,
- uid_t uid, gid_t gid, int flags)
-{
- int ret;
- char fullpath[LTTNG_PATH_MAX];
-
- ret = get_full_path(handle, name, fullpath, sizeof(fullpath));
- if (ret) {
- errno = ENOMEM;
- goto end;
- }
-
- ret = run_as_rmdir_recursive(fullpath, uid, gid, flags);
-end:
- return ret;
-}
-
-#endif /* HAVE_DIRFD */
-
-/* Common implementation. */
-
-/*
- * On some filesystems (e.g. nfs), mkdir will validate access rights before
- * checking for the existence of the path element. This means that on a setup
- * where "/home/" is a mounted NFS share, and running as an unpriviledged user,
- * recursively creating a path of the form "/home/my_user/trace/" will fail with
- * EACCES on mkdir("/home", ...).
- *
- * Checking the path for existence allows us to work around this behaviour.
- */
-static
-int create_directory_check_exists(const struct lttng_directory_handle *handle,
- const char *path, mode_t mode)
-{
- int ret = 0;
- struct stat st;
-
- ret = lttng_directory_handle_stat(handle, path, &st);
- if (ret == 0) {
- if (S_ISDIR(st.st_mode)) {
- /* Directory exists, skip. */
- goto end;
- } else {
- /* Exists, but is not a directory. */
- errno = ENOTDIR;
- ret = -1;
- goto end;
- }
- } else if (errno != ENOENT) {
- goto end;
- }
-
- /*
- * Let mkdir handle other errors as the caller expects mkdir
- * semantics.
- */
- ret = lttng_directory_handle_mkdir(handle, path, mode);
-end:
- return ret;
-}
-
-static
-int create_directory_recursive(const struct lttng_directory_handle *handle,
- const char *path, mode_t mode)
-{
- char *p, tmp[LTTNG_PATH_MAX];
- size_t len;
- int ret;
-
- LTTNG_ASSERT(path);
-
- ret = lttng_strncpy(tmp, path, sizeof(tmp));
- if (ret) {
- ERR("Failed to create directory: provided path's length (%zu bytes) exceeds the maximal allowed length (%zu bytes)",
- strlen(path) + 1, sizeof(tmp));
- goto error;
- }
-
- len = strlen(path);
- if (tmp[len - 1] == '/') {
- tmp[len - 1] = 0;
- }
-
- for (p = tmp + 1; *p; p++) {
- if (*p == '/') {
- *p = 0;
- if (tmp[strlen(tmp) - 1] == '.' &&
- tmp[strlen(tmp) - 2] == '.' &&
- tmp[strlen(tmp) - 3] == '/') {
- ERR("Using '/../' is not permitted in the trace path (%s)",
- tmp);
- ret = -1;
- goto error;
- }
- ret = create_directory_check_exists(handle, tmp, mode);
- if (ret < 0) {
- if (errno != EACCES) {
- PERROR("Failed to create directory \"%s\"",
- path);
- ret = -errno;
- goto error;
- }
- }
- *p = '/';
- }
- }
-
- ret = create_directory_check_exists(handle, tmp, mode);
- if (ret < 0) {
- PERROR("mkdirat recursive last element");
- ret = -errno;
- }
-error:
- return ret;
-}
-
-bool lttng_directory_handle_get(struct lttng_directory_handle *handle)
-{
- return urcu_ref_get_unless_zero(&handle->ref);
-}
-
-void lttng_directory_handle_put(struct lttng_directory_handle *handle)
-{
- if (!handle) {
- return;
- }
- LTTNG_ASSERT(handle->ref.refcount);
- urcu_ref_put(&handle->ref, lttng_directory_handle_release);
-}
-
-int lttng_directory_handle_create_subdirectory_as_user(
- const struct lttng_directory_handle *handle,
- const char *subdirectory,
- mode_t mode, const struct lttng_credentials *creds)
-{
- int ret;
-
- if (!creds) {
- /* Run as current user. */
- ret = create_directory_check_exists(handle,
- subdirectory, mode);
- } else {
- ret = _run_as_mkdir(handle, subdirectory, mode,
- lttng_credentials_get_uid(creds),
- lttng_credentials_get_gid(creds));
- }
-
- return ret;
-}
-
-int lttng_directory_handle_create_subdirectory_recursive_as_user(
- const struct lttng_directory_handle *handle,
- const char *subdirectory_path,
- mode_t mode, const struct lttng_credentials *creds)
-{
- int ret;
-
- if (!creds) {
- /* Run as current user. */
- ret = create_directory_recursive(handle,
- subdirectory_path, mode);
- } else {
- ret = _run_as_mkdir_recursive(handle, subdirectory_path,
- mode, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
- }
-
- return ret;
-}
-
-int lttng_directory_handle_create_subdirectory(
- const struct lttng_directory_handle *handle,
- const char *subdirectory,
- mode_t mode)
-{
- return lttng_directory_handle_create_subdirectory_as_user(
- handle, subdirectory, mode, NULL);
-}
-
-int lttng_directory_handle_create_subdirectory_recursive(
- const struct lttng_directory_handle *handle,
- const char *subdirectory_path,
- mode_t mode)
-{
- return lttng_directory_handle_create_subdirectory_recursive_as_user(
- handle, subdirectory_path, mode, NULL);
-}
-
-int lttng_directory_handle_open_file_as_user(
- const struct lttng_directory_handle *handle,
- const char *filename,
- int flags, mode_t mode,
- const struct lttng_credentials *creds)
-{
- int ret;
-
- if (!creds) {
- /* Run as current user. */
- ret = lttng_directory_handle_open(handle, filename, flags,
- mode);
- } else {
- ret = _run_as_open(handle, filename, flags, mode,
- lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
- }
- return ret;
-}
-
-int lttng_directory_handle_open_file(
- const struct lttng_directory_handle *handle,
- const char *filename,
- int flags, mode_t mode)
-{
- return lttng_directory_handle_open_file_as_user(handle, filename, flags,
- mode, NULL);
-}
-
-int lttng_directory_handle_unlink_file_as_user(
- const struct lttng_directory_handle *handle,
- const char *filename,
- const struct lttng_credentials *creds)
-{
- int ret;
-
- if (!creds) {
- /* Run as current user. */
- ret = lttng_directory_handle_unlink(handle, filename);
- } else {
- ret = _run_as_unlink(handle, filename, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
- }
- return ret;
-}
-
-int lttng_directory_handle_unlink_file(
- const struct lttng_directory_handle *handle,
- const char *filename)
-{
- return lttng_directory_handle_unlink_file_as_user(handle,
- filename, NULL);
-}
-
-int lttng_directory_handle_rename(
- const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name)
-{
- return lttng_directory_handle_rename_as_user(old_handle, old_name,
- new_handle, new_name, NULL);
-}
-
-int lttng_directory_handle_rename_as_user(
- const struct lttng_directory_handle *old_handle,
- const char *old_name,
- const struct lttng_directory_handle *new_handle,
- const char *new_name,
- const struct lttng_credentials *creds)
-{
- int ret;
-
- if (!creds) {
- /* Run as current user. */
- ret = _lttng_directory_handle_rename(old_handle,
- old_name, new_handle, new_name);
- } else {
- ret = _run_as_rename(old_handle, old_name, new_handle,
- new_name, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
- }
- return ret;
-}
-
-int lttng_directory_handle_remove_subdirectory(
- const struct lttng_directory_handle *handle,
- const char *name)
-{
- return lttng_directory_handle_remove_subdirectory_as_user(handle, name,
- NULL);
-}
-
-int lttng_directory_handle_remove_subdirectory_as_user(
- const struct lttng_directory_handle *handle,
- const char *name,
- const struct lttng_credentials *creds)
-{
- int ret;
-
- if (!creds) {
- /* Run as current user. */
- ret = lttng_directory_handle_rmdir(handle, name);
- } else {
- ret = _run_as_rmdir(handle, name, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
- }
- return ret;
-}
-
-struct rmdir_frame {
- ssize_t parent_frame_idx;
- DIR *dir;
- bool empty;
- /* Size including '\0'. */
- size_t path_size;
-};
-
-static
-void rmdir_frame_fini(void *data)
-{
- int ret;
- struct rmdir_frame *frame = data;
-
- ret = closedir(frame->dir);
- if (ret == -1) {
- PERROR("Failed to close directory stream");
- }
-}
-
-static
-int remove_directory_recursive(const struct lttng_directory_handle *handle,
- const char *path, int flags)
-{
- int ret;
- struct lttng_dynamic_array frames;
- size_t current_frame_idx = 0;
- struct rmdir_frame initial_frame = {
- .parent_frame_idx = -1,
- .dir = lttng_directory_handle_opendir(handle, path),
- .empty = true,
- .path_size = strlen(path) + 1,
- };
- struct lttng_dynamic_buffer current_path;
- const char separator = '/';
-
- lttng_dynamic_buffer_init(¤t_path);
- lttng_dynamic_array_init(&frames, sizeof(struct rmdir_frame),
- rmdir_frame_fini);
-
- if (flags & ~(LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG |
- LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG)) {
- ERR("Unknown flags %d", flags);
- ret = -1;
- goto end;
- }
-
- if (!initial_frame.dir) {
- if (flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG &&
- errno == ENOENT) {
- DBG("Cannot rmdir \"%s\": root does not exist", path);
- ret = 0;
- goto end;
- } else {
- PERROR("Failed to rmdir \"%s\"", path);
- ret = -1;
- goto end;
- }
- }
-
- ret = lttng_dynamic_array_add_element(&frames, &initial_frame);
- if (ret) {
- ERR("Failed to push context frame during recursive directory removal");
- rmdir_frame_fini(&initial_frame);
- goto end;
- }
-
- ret = lttng_dynamic_buffer_append(
- ¤t_path, path, initial_frame.path_size);
- if (ret) {
- ERR("Failed to set initial path during recursive directory removal");
- ret = -1;
- goto end;
- }
-
- while (lttng_dynamic_array_get_count(&frames) > 0) {
- struct dirent *entry;
- struct rmdir_frame *current_frame =
- lttng_dynamic_array_get_element(
- &frames, current_frame_idx);
-
- LTTNG_ASSERT(current_frame->dir);
- ret = lttng_dynamic_buffer_set_size(
- ¤t_path, current_frame->path_size);
- LTTNG_ASSERT(!ret);
- current_path.data[current_path.size - 1] = '\0';
-
- while ((entry = readdir(current_frame->dir))) {
- struct stat st;
-
- if (!strcmp(entry->d_name, ".") ||
- !strcmp(entry->d_name, "..")) {
- continue;
- }
-
- /* Set current_path to the entry's path. */
- ret = lttng_dynamic_buffer_set_size(
- ¤t_path, current_path.size - 1);
- LTTNG_ASSERT(!ret);
- ret = lttng_dynamic_buffer_append(¤t_path,
- &separator, sizeof(separator));
- if (ret) {
- goto end;
- }
- ret = lttng_dynamic_buffer_append(¤t_path,
- entry->d_name,
- strlen(entry->d_name) + 1);
- if (ret) {
- goto end;
- }
-
- if (lttng_directory_handle_stat(
- handle, current_path.data, &st)) {
- if ((flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG) &&
- errno == ENOENT) {
- break;
- }
- PERROR("Failed to stat \"%s\"",
- current_path.data);
- ret = -1;
- goto end;
- }
-
- if (!S_ISDIR(st.st_mode)) {
- if (flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG) {
- current_frame->empty = false;
- break;
- } else {
- /* Not empty, abort. */
- DBG("Directory \"%s\" is not empty; refusing to remove directory",
- current_path.data);
- ret = -1;
- goto end;
- }
- } else {
- struct rmdir_frame new_frame = {
- .path_size = current_path.size,
- .dir = lttng_directory_handle_opendir(
- handle,
- current_path.data),
- .empty = true,
- .parent_frame_idx = current_frame_idx,
- };
-
- if (!new_frame.dir) {
- if (flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG &&
- errno == ENOENT) {
- DBG("Non-existing directory stream during recursive directory removal");
- break;
- } else {
- PERROR("Failed to open directory stream during recursive directory removal");
- ret = -1;
- goto end;
- }
- }
- ret = lttng_dynamic_array_add_element(
- &frames, &new_frame);
- if (ret) {
- ERR("Failed to push context frame during recursive directory removal");
- rmdir_frame_fini(&new_frame);
- goto end;
- }
- current_frame_idx++;
- /* We break iteration on readdir. */
- break;
- }
- }
- if (entry) {
- continue;
- }
-
- /* Pop rmdir frame. */
- if (current_frame->empty) {
- ret = lttng_directory_handle_rmdir(
- handle, current_path.data);
- if (ret) {
- if ((flags & LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG) ||
- errno != ENOENT) {
- PERROR("Failed to remove \"%s\" during recursive directory removal",
- current_path.data);
- goto end;
- }
- DBG("Non-existing directory stream during recursive directory removal");
- }
- } else if (current_frame->parent_frame_idx >= 0) {
- struct rmdir_frame *parent_frame;
-
- parent_frame = lttng_dynamic_array_get_element(&frames,
- current_frame->parent_frame_idx);
- LTTNG_ASSERT(parent_frame);
- parent_frame->empty = false;
- }
- ret = lttng_dynamic_array_remove_element(
- &frames, current_frame_idx);
- if (ret) {
- ERR("Failed to pop context frame during recursive directory removal");
- goto end;
- }
- current_frame_idx--;
- }
-end:
- lttng_dynamic_array_reset(&frames);
- lttng_dynamic_buffer_reset(¤t_path);
- return ret;
-}
-
-int lttng_directory_handle_remove_subdirectory_recursive(
- const struct lttng_directory_handle *handle,
- const char *name,
- int flags)
-{
- return lttng_directory_handle_remove_subdirectory_recursive_as_user(
- handle, name, NULL, flags);
-}
-
-int lttng_directory_handle_remove_subdirectory_recursive_as_user(
- const struct lttng_directory_handle *handle,
- const char *name,
- const struct lttng_credentials *creds,
- int flags)
-{
- int ret;
-
- if (!creds) {
- /* Run as current user. */
- ret = remove_directory_recursive(handle, name, flags);
- } else {
- ret = _run_as_rmdir_recursive(handle, name, lttng_credentials_get_uid(creds),
- lttng_credentials_get_gid(creds), flags);
- }
- return ret;
-}
--- /dev/null
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <common/compat/directory-handle.h>
+#include <common/error.h>
+#include <common/macros.h>
+#include <common/runas.h>
+#include <common/credentials.h>
+#include <lttng/constant.h>
+#include <common/dynamic-array.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+
+/*
+ * This compatibility layer shares a common "base" that is implemented
+ * in terms of an internal API. This file contains two implementations
+ * of the internal API below.
+ */
+static
+int lttng_directory_handle_mkdir(
+ const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode);
+static
+int _run_as_mkdir(const struct lttng_directory_handle *handle, const char *path,
+ mode_t mode, uid_t uid, gid_t gid);
+static
+int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode, uid_t uid, gid_t gid);
+static
+int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
+ const char *filename, int flags, mode_t mode);
+static
+int _run_as_open(const struct lttng_directory_handle *handle,
+ const char *filename,
+ int flags, mode_t mode, uid_t uid, gid_t gid);
+static
+int lttng_directory_handle_unlink(
+ const struct lttng_directory_handle *handle,
+ const char *filename);
+static
+int _run_as_unlink(const struct lttng_directory_handle *handle,
+ const char *filename, uid_t uid, gid_t gid);
+static
+int _lttng_directory_handle_rename(
+ const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name);
+static
+int _run_as_rename(const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name, uid_t uid, gid_t gid);
+static
+DIR *lttng_directory_handle_opendir(const struct lttng_directory_handle *handle,
+ const char *path);
+static
+int lttng_directory_handle_rmdir(
+ const struct lttng_directory_handle *handle, const char *name);
+static
+int _run_as_rmdir(const struct lttng_directory_handle *handle,
+ const char *name, uid_t uid, gid_t gid);
+static
+int _run_as_rmdir_recursive(
+ const struct lttng_directory_handle *handle, const char *name,
+ uid_t uid, gid_t gid, int flags);
+static
+void lttng_directory_handle_invalidate(struct lttng_directory_handle *handle);
+static
+void lttng_directory_handle_release(struct urcu_ref *ref);
+
+#ifdef HAVE_DIRFD
+
+/*
+ * Special inode number reserved to represent the "current working directory".
+ * ino_t is spec'ed as being an unsigned integral type.
+ */
+#define RESERVED_AT_FDCWD_INO \
+ ({ \
+ uint64_t reserved_val; \
+ switch (sizeof(ino_t)) { \
+ case 4: \
+ reserved_val = UINT32_MAX; \
+ break; \
+ case 8: \
+ reserved_val = UINT64_MAX; \
+ break; \
+ default: \
+ abort(); \
+ } \
+ (ino_t) reserved_val; \
+ })
+
+struct lttng_directory_handle *lttng_directory_handle_create(const char *path)
+{
+ lttng_directory_handle cwd_handle {};
+ cwd_handle.dirfd = AT_FDCWD;
+
+ /* Open a handle to the CWD if NULL is passed. */
+ return lttng_directory_handle_create_from_handle(path, &cwd_handle);
+}
+
+struct lttng_directory_handle *lttng_directory_handle_create_from_handle(
+ const char *path,
+ const struct lttng_directory_handle *ref_handle)
+{
+ int dirfd;
+ struct lttng_directory_handle *handle = NULL;
+
+ if (!path) {
+ handle = lttng_directory_handle_copy(ref_handle);
+ goto end;
+ }
+ if (!*path) {
+ ERR("Failed to initialize directory handle: provided path is an empty string");
+ goto end;
+ }
+
+ dirfd = openat(ref_handle->dirfd, path, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ if (dirfd == -1) {
+ PERROR("Failed to initialize directory handle to \"%s\"", path);
+ goto end;
+ }
+
+ handle = lttng_directory_handle_create_from_dirfd(dirfd);
+ if (!handle) {
+ goto error_close;
+ }
+end:
+ return handle;
+error_close:
+ if (close(dirfd)) {
+ PERROR("Failed to close directory file descriptor");
+ }
+ return NULL;
+}
+
+struct lttng_directory_handle *lttng_directory_handle_create_from_dirfd(
+ int dirfd)
+{
+ int ret;
+ struct lttng_directory_handle *handle = (lttng_directory_handle *) zmalloc(sizeof(*handle));
+ struct stat stat_buf;
+
+ if (!handle) {
+ goto end;
+ }
+
+ if (dirfd != AT_FDCWD) {
+ ret = fstat(dirfd, &stat_buf);
+ if (ret) {
+ PERROR("Failed to fstat directory file descriptor %i", dirfd);
+ lttng_directory_handle_release(&handle->ref);
+ handle = NULL;
+ goto end;
+ }
+ } else {
+ handle->directory_inode = RESERVED_AT_FDCWD_INO;
+ }
+ handle->dirfd = dirfd;
+ urcu_ref_init(&handle->ref);
+end:
+ return handle;
+}
+
+static
+void lttng_directory_handle_release(struct urcu_ref *ref)
+{
+ int ret;
+ struct lttng_directory_handle *handle =
+ container_of(ref, struct lttng_directory_handle, ref);
+
+ if (handle->destroy_cb) {
+ handle->destroy_cb(handle, handle->destroy_cb_data);
+ }
+
+ if (handle->dirfd == AT_FDCWD || handle->dirfd == -1) {
+ goto end;
+ }
+ ret = close(handle->dirfd);
+ if (ret == -1) {
+ PERROR("Failed to close directory file descriptor of directory handle");
+ }
+end:
+ lttng_directory_handle_invalidate(handle);
+ free(handle);
+}
+
+struct lttng_directory_handle *lttng_directory_handle_copy(
+ const struct lttng_directory_handle *handle)
+{
+ struct lttng_directory_handle *new_handle = NULL;
+
+ if (handle->dirfd == AT_FDCWD) {
+ new_handle = lttng_directory_handle_create_from_dirfd(AT_FDCWD);
+ } else {
+ const int new_dirfd = dup(handle->dirfd);
+
+ if (new_dirfd == -1) {
+ PERROR("Failed to duplicate directory file descriptor of directory handle");
+ goto end;
+ }
+ new_handle = lttng_directory_handle_create_from_dirfd(
+ new_dirfd);
+ if (!new_handle && close(new_dirfd)) {
+ PERROR("Failed to close directory file descriptor of directory handle");
+ }
+ }
+end:
+ return new_handle;
+}
+
+bool lttng_directory_handle_equals(const struct lttng_directory_handle *lhs,
+ const struct lttng_directory_handle *rhs)
+{
+ return lhs->directory_inode == rhs->directory_inode;
+}
+
+static
+void lttng_directory_handle_invalidate(struct lttng_directory_handle *handle)
+{
+ handle->dirfd = -1;
+}
+
+int lttng_directory_handle_stat(const struct lttng_directory_handle *handle,
+ const char *path, struct stat *st)
+{
+ return fstatat(handle->dirfd, path, st, 0);
+}
+
+bool lttng_directory_handle_uses_fd(
+ const struct lttng_directory_handle *handle)
+{
+ return handle->dirfd != AT_FDCWD;
+}
+
+static
+int lttng_directory_handle_mkdir(
+ const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode)
+{
+ return mkdirat(handle->dirfd, path, mode);
+}
+
+static
+int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
+ const char *filename, int flags, mode_t mode)
+{
+ return openat(handle->dirfd, filename, flags, mode);
+}
+
+static
+int _run_as_open(const struct lttng_directory_handle *handle,
+ const char *filename,
+ int flags, mode_t mode, uid_t uid, gid_t gid)
+{
+ return run_as_openat(handle->dirfd, filename, flags, mode, uid, gid);
+}
+
+static
+int _run_as_unlink(const struct lttng_directory_handle *handle,
+ const char *filename, uid_t uid, gid_t gid)
+{
+ return run_as_unlinkat(handle->dirfd, filename, uid, gid);
+}
+
+static
+int lttng_directory_handle_unlink(
+ const struct lttng_directory_handle *handle,
+ const char *filename)
+{
+ return unlinkat(handle->dirfd, filename, 0);
+}
+
+static
+int _run_as_mkdir(const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+ return run_as_mkdirat(handle->dirfd, path, mode, uid, gid);
+}
+
+static
+int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+ return run_as_mkdirat_recursive(handle->dirfd, path, mode, uid, gid);
+}
+
+static
+int _lttng_directory_handle_rename(
+ const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name)
+{
+ return renameat(old_handle->dirfd, old_name,
+ new_handle->dirfd, new_name);
+}
+
+static
+int _run_as_rename(const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name, uid_t uid, gid_t gid)
+{
+ return run_as_renameat(old_handle->dirfd, old_name, new_handle->dirfd,
+ new_name, uid, gid);
+}
+
+static
+DIR *lttng_directory_handle_opendir(const struct lttng_directory_handle *handle,
+ const char *path)
+{
+ DIR *dir_stream = NULL;
+ int fd = openat(handle->dirfd, path, O_RDONLY);
+
+ if (fd < 0) {
+ goto end;
+ }
+
+ dir_stream = fdopendir(fd);
+ if (!dir_stream) {
+ int ret;
+
+ PERROR("Failed to open directory stream");
+ ret = close(fd);
+ if (ret) {
+ PERROR("Failed to close file descriptor to %s", path);
+ }
+ goto end;
+ }
+
+end:
+ return dir_stream;
+}
+
+static
+int lttng_directory_handle_rmdir(
+ const struct lttng_directory_handle *handle, const char *name)
+{
+ int ret = unlinkat(handle->dirfd, name, AT_REMOVEDIR);
+ if (ret) {
+ PERROR("Failed to remove directory `%s`", name);
+ }
+
+ return ret;
+}
+
+static
+int _run_as_rmdir(const struct lttng_directory_handle *handle,
+ const char *name, uid_t uid, gid_t gid)
+{
+ return run_as_rmdirat(handle->dirfd, name, uid, gid);
+}
+
+static
+int _run_as_rmdir_recursive(
+ const struct lttng_directory_handle *handle, const char *name,
+ uid_t uid, gid_t gid, int flags)
+{
+ return run_as_rmdirat_recursive(handle->dirfd, name, uid, gid, flags);
+}
+
+#else /* HAVE_DIRFD */
+
+static
+int get_full_path(const struct lttng_directory_handle *handle,
+ const char *subdirectory, char *fullpath, size_t size)
+{
+ int ret;
+ const bool subdirectory_is_absolute =
+ subdirectory && *subdirectory == '/';
+ const char * const base = subdirectory_is_absolute ?
+ subdirectory : handle->base_path;
+ const char * const end = subdirectory && !subdirectory_is_absolute ?
+ subdirectory : NULL;
+ const size_t base_len = strlen(base);
+ const size_t end_len = end ? strlen(end) : 0;
+ const bool add_separator_slash = end && base[base_len - 1] != '/';
+ const bool add_trailing_slash = end && end[end_len - 1] != '/';
+
+ ret = snprintf(fullpath, size, "%s%s%s%s",
+ base,
+ add_separator_slash ? "/" : "",
+ end ? end : "",
+ add_trailing_slash ? "/" : "");
+ if (ret == -1 || ret >= size) {
+ ERR("Failed to format subdirectory from directory handle");
+ ret = -1;
+ goto end;
+ }
+ ret = 0;
+end:
+ return ret;
+}
+
+static
+struct lttng_directory_handle *_lttng_directory_handle_create(char *path)
+{
+ struct lttng_directory_handle *handle = zmalloc(sizeof(*handle));
+
+ if (!handle) {
+ goto end;
+ }
+ urcu_ref_init(&handle->ref);
+ handle->base_path = path;
+end:
+ return handle;
+}
+
+struct lttng_directory_handle *lttng_directory_handle_create(
+ const char *path)
+{
+ int ret;
+ const char *cwd = "";
+ size_t cwd_len, path_len;
+ char cwd_buf[LTTNG_PATH_MAX] = {};
+ char handle_buf[LTTNG_PATH_MAX] = {};
+ struct lttng_directory_handle *new_handle = NULL;
+ bool add_cwd_slash = false, add_trailing_slash = false;
+ const struct lttng_directory_handle cwd_handle = {
+ .base_path = handle_buf,
+ };
+
+ path_len = path ? strlen(path) : 0;
+ add_trailing_slash = path && path[path_len - 1] != '/';
+ if (!path || (path && *path != '/')) {
+ cwd = getcwd(cwd_buf, sizeof(cwd_buf));
+ if (!cwd) {
+ PERROR("Failed to initialize directory handle, can't get current working directory");
+ ret = -1;
+ goto end;
+ }
+ cwd_len = strlen(cwd);
+ if (cwd_len == 0) {
+ ERR("Failed to initialize directory handle, current working directory path has a length of 0");
+ ret = -1;
+ goto end;
+ }
+ add_cwd_slash = cwd[cwd_len - 1] != '/';
+ }
+
+ ret = snprintf(handle_buf, sizeof(handle_buf), "%s%s%s%s",
+ cwd,
+ add_cwd_slash ? "/" : "",
+ path ? : "",
+ add_trailing_slash ? "/" : "");
+ if (ret == -1 || ret >= LTTNG_PATH_MAX) {
+ ERR("Failed to initialize directory handle, failed to format directory path");
+ goto end;
+ }
+
+ new_handle = lttng_directory_handle_create_from_handle(path, &cwd_handle);
+end:
+ return new_handle;
+}
+
+struct lttng_directory_handle *lttng_directory_handle_create_from_handle(
+ const char *path,
+ const struct lttng_directory_handle *ref_handle)
+{
+ int ret;
+ size_t path_len, handle_path_len;
+ bool add_trailing_slash;
+ struct stat stat_buf;
+ struct lttng_directory_handle *new_handle = NULL;
+ char *new_path = NULL;
+
+ LTTNG_ASSERT(ref_handle && ref_handle->base_path);
+
+ ret = lttng_directory_handle_stat(ref_handle, path, &stat_buf);
+ if (ret == -1) {
+ PERROR("Failed to create directory handle");
+ goto end;
+ } else if (!S_ISDIR(stat_buf.st_mode)) {
+ char full_path[LTTNG_PATH_MAX];
+
+ /* Best effort for logging purposes. */
+ ret = get_full_path(ref_handle, path, full_path,
+ sizeof(full_path));
+ if (ret) {
+ full_path[0] = '\0';
+ }
+
+ ERR("Failed to initialize directory handle to \"%s\": not a directory",
+ full_path);
+ goto end;
+ }
+ if (!path) {
+ new_handle = lttng_directory_handle_copy(ref_handle);
+ goto end;
+ }
+
+ path_len = strlen(path);
+ if (path_len == 0) {
+ ERR("Failed to initialize directory handle: provided path is an empty string");
+ ret = -1;
+ goto end;
+ }
+ if (*path == '/') {
+ new_path = strdup(path);
+ if (!new_path) {
+ goto end;
+ }
+ /* Takes ownership of new_path. */
+ new_handle = _lttng_directory_handle_create(new_path);
+ new_path = NULL;
+ goto end;
+ }
+
+ add_trailing_slash = path[path_len - 1] != '/';
+
+ handle_path_len = strlen(ref_handle->base_path) + path_len +
+ !!add_trailing_slash;
+ if (handle_path_len >= LTTNG_PATH_MAX) {
+ ERR("Failed to initialize directory handle as the resulting path's length (%zu bytes) exceeds the maximal allowed length (%d bytes)",
+ handle_path_len, LTTNG_PATH_MAX);
+ goto end;
+ }
+ new_path = zmalloc(handle_path_len);
+ if (!new_path) {
+ PERROR("Failed to initialize directory handle");
+ goto end;
+ }
+
+ ret = sprintf(new_handle->base_path, "%s%s%s",
+ ref_handle->base_path,
+ path,
+ add_trailing_slash ? "/" : "");
+ if (ret == -1 || ret >= handle_path_len) {
+ ERR("Failed to initialize directory handle: path formatting failed");
+ goto end;
+ }
+ new_handle = _lttng_directory_handle_create(new_path);
+ new_path = NULL;
+end:
+ free(new_path);
+ return new_handle;
+}
+
+struct lttng_directory_handle *lttng_directory_handle_create_from_dirfd(
+ int dirfd)
+{
+ LTTNG_ASSERT(dirfd == AT_FDCWD);
+ return lttng_directory_handle_create(NULL);
+}
+
+static
+void lttng_directory_handle_release(struct urcu_ref *ref)
+{
+ struct lttng_directory_handle *handle =
+ container_of(ref, struct lttng_directory_handle, ref);
+
+ free(handle->base_path);
+ lttng_directory_handle_invalidate(handle);
+ free(handle);
+}
+
+struct lttng_directory_handle *lttng_directory_handle_copy(
+ const struct lttng_directory_handle *handle)
+{
+ struct lttng_directory_handle *new_handle = NULL;
+ char *new_path = NULL;
+
+ if (handle->base_path) {
+ new_path = strdup(handle->base_path);
+ if (!new_path) {
+ goto end;
+ }
+ }
+ new_handle = _lttng_directory_handle_create(new_path);
+end:
+ return new_handle;
+}
+
+bool lttng_directory_handle_equals(const struct lttng_directory_handle *lhs,
+ const struct lttng_directory_handle *rhs)
+{
+ return strcmp(lhs->base_path, rhs->base_path) == 0;
+}
+
+static
+void lttng_directory_handle_invalidate(struct lttng_directory_handle *handle)
+{
+ handle->base_path = NULL;
+}
+
+int lttng_directory_handle_stat(const struct lttng_directory_handle *handle,
+ const char *subdirectory, struct stat *st)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, subdirectory, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = stat(fullpath, st);
+end:
+ return ret;
+}
+
+bool lttng_directory_handle_uses_fd(
+ const struct lttng_directory_handle *handle)
+{
+ return false;
+}
+
+static
+int lttng_directory_handle_mkdir(const struct lttng_directory_handle *handle,
+ const char *subdirectory, mode_t mode)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, subdirectory, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = mkdir(fullpath, mode);
+end:
+ return ret;
+}
+
+static
+int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
+ const char *filename, int flags, mode_t mode)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = open(fullpath, flags, mode);
+end:
+ return ret;
+}
+
+static
+int lttng_directory_handle_unlink(
+ const struct lttng_directory_handle *handle,
+ const char *filename)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = unlink(fullpath);
+end:
+ return ret;
+}
+
+static
+int _run_as_mkdir(const struct lttng_directory_handle *handle, const char *path,
+ mode_t mode, uid_t uid, gid_t gid)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, path, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = run_as_mkdir(fullpath, mode, uid, gid);
+end:
+ return ret;
+}
+
+static
+int _run_as_open(const struct lttng_directory_handle *handle,
+ const char *filename,
+ int flags, mode_t mode, uid_t uid, gid_t gid)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = run_as_open(fullpath, flags, mode, uid, gid);
+end:
+ return ret;
+}
+
+static
+int _run_as_unlink(const struct lttng_directory_handle *handle,
+ const char *filename, uid_t uid, gid_t gid)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = run_as_unlink(fullpath, uid, gid);
+end:
+ return ret;
+}
+
+static
+int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, path, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = run_as_mkdir_recursive(fullpath, mode, uid, gid);
+end:
+ return ret;
+}
+
+static
+int _lttng_directory_handle_rename(
+ const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name)
+{
+ int ret;
+ char old_fullpath[LTTNG_PATH_MAX];
+ char new_fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(old_handle, old_name, old_fullpath,
+ sizeof(old_fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+ ret = get_full_path(new_handle, new_name, new_fullpath,
+ sizeof(new_fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = rename(old_fullpath, new_fullpath);
+end:
+ return ret;
+}
+
+static
+int _run_as_rename(const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name, uid_t uid, gid_t gid)
+{
+ int ret;
+ char old_fullpath[LTTNG_PATH_MAX];
+ char new_fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(old_handle, old_name, old_fullpath,
+ sizeof(old_fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+ ret = get_full_path(new_handle, new_name, new_fullpath,
+ sizeof(new_fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = run_as_rename(old_fullpath, new_fullpath, uid, gid);
+end:
+ return ret;
+}
+
+static
+DIR *lttng_directory_handle_opendir(const struct lttng_directory_handle *handle,
+ const char *path)
+{
+ int ret;
+ DIR *dir_stream = NULL;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, path, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ dir_stream = opendir(fullpath);
+end:
+ return dir_stream;
+}
+
+static
+int lttng_directory_handle_rmdir(
+ const struct lttng_directory_handle *handle, const char *name)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, name, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = rmdir(fullpath);
+end:
+ return ret;
+}
+
+static
+int _run_as_rmdir(const struct lttng_directory_handle *handle,
+ const char *name, uid_t uid, gid_t gid)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, name, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = run_as_rmdir(fullpath, uid, gid);
+end:
+ return ret;
+}
+
+static
+int _run_as_rmdir_recursive(
+ const struct lttng_directory_handle *handle, const char *name,
+ uid_t uid, gid_t gid, int flags)
+{
+ int ret;
+ char fullpath[LTTNG_PATH_MAX];
+
+ ret = get_full_path(handle, name, fullpath, sizeof(fullpath));
+ if (ret) {
+ errno = ENOMEM;
+ goto end;
+ }
+
+ ret = run_as_rmdir_recursive(fullpath, uid, gid, flags);
+end:
+ return ret;
+}
+
+#endif /* HAVE_DIRFD */
+
+/* Common implementation. */
+
+/*
+ * On some filesystems (e.g. nfs), mkdir will validate access rights before
+ * checking for the existence of the path element. This means that on a setup
+ * where "/home/" is a mounted NFS share, and running as an unpriviledged user,
+ * recursively creating a path of the form "/home/my_user/trace/" will fail with
+ * EACCES on mkdir("/home", ...).
+ *
+ * Checking the path for existence allows us to work around this behaviour.
+ */
+static
+int create_directory_check_exists(const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode)
+{
+ int ret = 0;
+ struct stat st;
+
+ ret = lttng_directory_handle_stat(handle, path, &st);
+ if (ret == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ /* Directory exists, skip. */
+ goto end;
+ } else {
+ /* Exists, but is not a directory. */
+ errno = ENOTDIR;
+ ret = -1;
+ goto end;
+ }
+ } else if (errno != ENOENT) {
+ goto end;
+ }
+
+ /*
+ * Let mkdir handle other errors as the caller expects mkdir
+ * semantics.
+ */
+ ret = lttng_directory_handle_mkdir(handle, path, mode);
+end:
+ return ret;
+}
+
+static
+int create_directory_recursive(const struct lttng_directory_handle *handle,
+ const char *path, mode_t mode)
+{
+ char *p, tmp[LTTNG_PATH_MAX];
+ size_t len;
+ int ret;
+
+ LTTNG_ASSERT(path);
+
+ ret = lttng_strncpy(tmp, path, sizeof(tmp));
+ if (ret) {
+ ERR("Failed to create directory: provided path's length (%zu bytes) exceeds the maximal allowed length (%zu bytes)",
+ strlen(path) + 1, sizeof(tmp));
+ goto error;
+ }
+
+ len = strlen(path);
+ if (tmp[len - 1] == '/') {
+ tmp[len - 1] = 0;
+ }
+
+ for (p = tmp + 1; *p; p++) {
+ if (*p == '/') {
+ *p = 0;
+ if (tmp[strlen(tmp) - 1] == '.' &&
+ tmp[strlen(tmp) - 2] == '.' &&
+ tmp[strlen(tmp) - 3] == '/') {
+ ERR("Using '/../' is not permitted in the trace path (%s)",
+ tmp);
+ ret = -1;
+ goto error;
+ }
+ ret = create_directory_check_exists(handle, tmp, mode);
+ if (ret < 0) {
+ if (errno != EACCES) {
+ PERROR("Failed to create directory \"%s\"",
+ path);
+ ret = -errno;
+ goto error;
+ }
+ }
+ *p = '/';
+ }
+ }
+
+ ret = create_directory_check_exists(handle, tmp, mode);
+ if (ret < 0) {
+ PERROR("mkdirat recursive last element");
+ ret = -errno;
+ }
+error:
+ return ret;
+}
+
+bool lttng_directory_handle_get(struct lttng_directory_handle *handle)
+{
+ return urcu_ref_get_unless_zero(&handle->ref);
+}
+
+void lttng_directory_handle_put(struct lttng_directory_handle *handle)
+{
+ if (!handle) {
+ return;
+ }
+ LTTNG_ASSERT(handle->ref.refcount);
+ urcu_ref_put(&handle->ref, lttng_directory_handle_release);
+}
+
+int lttng_directory_handle_create_subdirectory_as_user(
+ const struct lttng_directory_handle *handle,
+ const char *subdirectory,
+ mode_t mode, const struct lttng_credentials *creds)
+{
+ int ret;
+
+ if (!creds) {
+ /* Run as current user. */
+ ret = create_directory_check_exists(handle,
+ subdirectory, mode);
+ } else {
+ ret = _run_as_mkdir(handle, subdirectory, mode,
+ lttng_credentials_get_uid(creds),
+ lttng_credentials_get_gid(creds));
+ }
+
+ return ret;
+}
+
+int lttng_directory_handle_create_subdirectory_recursive_as_user(
+ const struct lttng_directory_handle *handle,
+ const char *subdirectory_path,
+ mode_t mode, const struct lttng_credentials *creds)
+{
+ int ret;
+
+ if (!creds) {
+ /* Run as current user. */
+ ret = create_directory_recursive(handle,
+ subdirectory_path, mode);
+ } else {
+ ret = _run_as_mkdir_recursive(handle, subdirectory_path,
+ mode, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
+ }
+
+ return ret;
+}
+
+int lttng_directory_handle_create_subdirectory(
+ const struct lttng_directory_handle *handle,
+ const char *subdirectory,
+ mode_t mode)
+{
+ return lttng_directory_handle_create_subdirectory_as_user(
+ handle, subdirectory, mode, NULL);
+}
+
+int lttng_directory_handle_create_subdirectory_recursive(
+ const struct lttng_directory_handle *handle,
+ const char *subdirectory_path,
+ mode_t mode)
+{
+ return lttng_directory_handle_create_subdirectory_recursive_as_user(
+ handle, subdirectory_path, mode, NULL);
+}
+
+int lttng_directory_handle_open_file_as_user(
+ const struct lttng_directory_handle *handle,
+ const char *filename,
+ int flags, mode_t mode,
+ const struct lttng_credentials *creds)
+{
+ int ret;
+
+ if (!creds) {
+ /* Run as current user. */
+ ret = lttng_directory_handle_open(handle, filename, flags,
+ mode);
+ } else {
+ ret = _run_as_open(handle, filename, flags, mode,
+ lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
+ }
+ return ret;
+}
+
+int lttng_directory_handle_open_file(
+ const struct lttng_directory_handle *handle,
+ const char *filename,
+ int flags, mode_t mode)
+{
+ return lttng_directory_handle_open_file_as_user(handle, filename, flags,
+ mode, NULL);
+}
+
+int lttng_directory_handle_unlink_file_as_user(
+ const struct lttng_directory_handle *handle,
+ const char *filename,
+ const struct lttng_credentials *creds)
+{
+ int ret;
+
+ if (!creds) {
+ /* Run as current user. */
+ ret = lttng_directory_handle_unlink(handle, filename);
+ } else {
+ ret = _run_as_unlink(handle, filename, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
+ }
+ return ret;
+}
+
+int lttng_directory_handle_unlink_file(
+ const struct lttng_directory_handle *handle,
+ const char *filename)
+{
+ return lttng_directory_handle_unlink_file_as_user(handle,
+ filename, NULL);
+}
+
+int lttng_directory_handle_rename(
+ const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name)
+{
+ return lttng_directory_handle_rename_as_user(old_handle, old_name,
+ new_handle, new_name, NULL);
+}
+
+int lttng_directory_handle_rename_as_user(
+ const struct lttng_directory_handle *old_handle,
+ const char *old_name,
+ const struct lttng_directory_handle *new_handle,
+ const char *new_name,
+ const struct lttng_credentials *creds)
+{
+ int ret;
+
+ if (!creds) {
+ /* Run as current user. */
+ ret = _lttng_directory_handle_rename(old_handle,
+ old_name, new_handle, new_name);
+ } else {
+ ret = _run_as_rename(old_handle, old_name, new_handle,
+ new_name, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
+ }
+ return ret;
+}
+
+int lttng_directory_handle_remove_subdirectory(
+ const struct lttng_directory_handle *handle,
+ const char *name)
+{
+ return lttng_directory_handle_remove_subdirectory_as_user(handle, name,
+ NULL);
+}
+
+int lttng_directory_handle_remove_subdirectory_as_user(
+ const struct lttng_directory_handle *handle,
+ const char *name,
+ const struct lttng_credentials *creds)
+{
+ int ret;
+
+ if (!creds) {
+ /* Run as current user. */
+ ret = lttng_directory_handle_rmdir(handle, name);
+ } else {
+ ret = _run_as_rmdir(handle, name, lttng_credentials_get_uid(creds), lttng_credentials_get_gid(creds));
+ }
+ return ret;
+}
+
+struct rmdir_frame {
+ ssize_t parent_frame_idx;
+ DIR *dir;
+ bool empty;
+ /* Size including '\0'. */
+ size_t path_size;
+};
+
+static
+void rmdir_frame_fini(void *data)
+{
+ int ret;
+ struct rmdir_frame *frame = (rmdir_frame *) data;
+
+ ret = closedir(frame->dir);
+ if (ret == -1) {
+ PERROR("Failed to close directory stream");
+ }
+}
+
+static
+int remove_directory_recursive(const struct lttng_directory_handle *handle,
+ const char *path, int flags)
+{
+ int ret;
+ struct lttng_dynamic_array frames;
+ size_t current_frame_idx = 0;
+ struct rmdir_frame initial_frame = {
+ .parent_frame_idx = -1,
+ .dir = lttng_directory_handle_opendir(handle, path),
+ .empty = true,
+ .path_size = strlen(path) + 1,
+ };
+ struct lttng_dynamic_buffer current_path;
+ const char separator = '/';
+
+ lttng_dynamic_buffer_init(¤t_path);
+ lttng_dynamic_array_init(&frames, sizeof(struct rmdir_frame),
+ rmdir_frame_fini);
+
+ if (flags & ~(LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG |
+ LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG)) {
+ ERR("Unknown flags %d", flags);
+ ret = -1;
+ goto end;
+ }
+
+ if (!initial_frame.dir) {
+ if (flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG &&
+ errno == ENOENT) {
+ DBG("Cannot rmdir \"%s\": root does not exist", path);
+ ret = 0;
+ goto end;
+ } else {
+ PERROR("Failed to rmdir \"%s\"", path);
+ ret = -1;
+ goto end;
+ }
+ }
+
+ ret = lttng_dynamic_array_add_element(&frames, &initial_frame);
+ if (ret) {
+ ERR("Failed to push context frame during recursive directory removal");
+ rmdir_frame_fini(&initial_frame);
+ goto end;
+ }
+
+ ret = lttng_dynamic_buffer_append(
+ ¤t_path, path, initial_frame.path_size);
+ if (ret) {
+ ERR("Failed to set initial path during recursive directory removal");
+ ret = -1;
+ goto end;
+ }
+
+ while (lttng_dynamic_array_get_count(&frames) > 0) {
+ struct dirent *entry;
+ struct rmdir_frame *current_frame =
+ (rmdir_frame *) lttng_dynamic_array_get_element(
+ &frames, current_frame_idx);
+
+ LTTNG_ASSERT(current_frame->dir);
+ ret = lttng_dynamic_buffer_set_size(
+ ¤t_path, current_frame->path_size);
+ LTTNG_ASSERT(!ret);
+ current_path.data[current_path.size - 1] = '\0';
+
+ while ((entry = readdir(current_frame->dir))) {
+ struct stat st;
+
+ if (!strcmp(entry->d_name, ".") ||
+ !strcmp(entry->d_name, "..")) {
+ continue;
+ }
+
+ /* Set current_path to the entry's path. */
+ ret = lttng_dynamic_buffer_set_size(
+ ¤t_path, current_path.size - 1);
+ LTTNG_ASSERT(!ret);
+ ret = lttng_dynamic_buffer_append(¤t_path,
+ &separator, sizeof(separator));
+ if (ret) {
+ goto end;
+ }
+ ret = lttng_dynamic_buffer_append(¤t_path,
+ entry->d_name,
+ strlen(entry->d_name) + 1);
+ if (ret) {
+ goto end;
+ }
+
+ if (lttng_directory_handle_stat(
+ handle, current_path.data, &st)) {
+ if ((flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG) &&
+ errno == ENOENT) {
+ break;
+ }
+ PERROR("Failed to stat \"%s\"",
+ current_path.data);
+ ret = -1;
+ goto end;
+ }
+
+ if (!S_ISDIR(st.st_mode)) {
+ if (flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG) {
+ current_frame->empty = false;
+ break;
+ } else {
+ /* Not empty, abort. */
+ DBG("Directory \"%s\" is not empty; refusing to remove directory",
+ current_path.data);
+ ret = -1;
+ goto end;
+ }
+ } else {
+ struct rmdir_frame new_frame = {
+ .parent_frame_idx = (ssize_t) current_frame_idx,
+ .dir = lttng_directory_handle_opendir(
+ handle,
+ current_path.data),
+ .empty = true,
+ .path_size = current_path.size,
+ };
+
+ if (!new_frame.dir) {
+ if (flags & LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG &&
+ errno == ENOENT) {
+ DBG("Non-existing directory stream during recursive directory removal");
+ break;
+ } else {
+ PERROR("Failed to open directory stream during recursive directory removal");
+ ret = -1;
+ goto end;
+ }
+ }
+ ret = lttng_dynamic_array_add_element(
+ &frames, &new_frame);
+ if (ret) {
+ ERR("Failed to push context frame during recursive directory removal");
+ rmdir_frame_fini(&new_frame);
+ goto end;
+ }
+ current_frame_idx++;
+ /* We break iteration on readdir. */
+ break;
+ }
+ }
+ if (entry) {
+ continue;
+ }
+
+ /* Pop rmdir frame. */
+ if (current_frame->empty) {
+ ret = lttng_directory_handle_rmdir(
+ handle, current_path.data);
+ if (ret) {
+ if ((flags & LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG) ||
+ errno != ENOENT) {
+ PERROR("Failed to remove \"%s\" during recursive directory removal",
+ current_path.data);
+ goto end;
+ }
+ DBG("Non-existing directory stream during recursive directory removal");
+ }
+ } else if (current_frame->parent_frame_idx >= 0) {
+ struct rmdir_frame *parent_frame;
+
+ parent_frame = (rmdir_frame *) lttng_dynamic_array_get_element(&frames,
+ current_frame->parent_frame_idx);
+ LTTNG_ASSERT(parent_frame);
+ parent_frame->empty = false;
+ }
+ ret = lttng_dynamic_array_remove_element(
+ &frames, current_frame_idx);
+ if (ret) {
+ ERR("Failed to pop context frame during recursive directory removal");
+ goto end;
+ }
+ current_frame_idx--;
+ }
+end:
+ lttng_dynamic_array_reset(&frames);
+ lttng_dynamic_buffer_reset(¤t_path);
+ return ret;
+}
+
+int lttng_directory_handle_remove_subdirectory_recursive(
+ const struct lttng_directory_handle *handle,
+ const char *name,
+ int flags)
+{
+ return lttng_directory_handle_remove_subdirectory_recursive_as_user(
+ handle, name, NULL, flags);
+}
+
+int lttng_directory_handle_remove_subdirectory_recursive_as_user(
+ const struct lttng_directory_handle *handle,
+ const char *name,
+ const struct lttng_credentials *creds,
+ int flags)
+{
+ int ret;
+
+ if (!creds) {
+ /* Run as current user. */
+ ret = remove_directory_recursive(handle, name, flags);
+ } else {
+ ret = _run_as_rmdir_recursive(handle, name, lttng_credentials_get_uid(creds),
+ lttng_credentials_get_gid(creds), flags);
+ }
+ return ret;
+}
#include <common/compat/errno.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#if (defined(__CYGWIN__))
typedef long long off64_t;
#endif
#error "Please add support for your OS."
#endif /* __linux__ , __FreeBSD__, __CYGWIN__, __sun__, __APPLE__ */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _COMPAT_FCNTL_H */
+++ /dev/null
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/utils.h>
-
-#include "poll.h"
-
-#if HAVE_EPOLL
-
-#include <fcntl.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-/*
- * Maximum number of fd we can monitor.
- *
- * For epoll(7), /proc/sys/fs/epoll/max_user_watches (since Linux 2.6.28) will
- * be used for the maximum size of the poll set. If this interface is not
- * available, according to the manpage, the max_user_watches value is 1/25 (4%)
- * of the available low memory divided by the registration cost in bytes which
- * is 90 bytes on a 32-bit kernel and 160 bytes on a 64-bit kernel.
- *
- */
-static unsigned int poll_max_size;
-
-/*
- * Resize the epoll events structure of the new size.
- *
- * Return 0 on success or else -1 with the current events pointer untouched.
- */
-static int resize_poll_event(struct lttng_poll_event *events,
- uint32_t new_size)
-{
- struct epoll_event *ptr;
-
- LTTNG_ASSERT(events);
-
- ptr = realloc(events->events, new_size * sizeof(*ptr));
- if (ptr == NULL) {
- PERROR("realloc epoll add");
- goto error;
- }
- if (new_size > events->alloc_size) {
- /* Zero newly allocated memory */
- memset(ptr + events->alloc_size, 0,
- (new_size - events->alloc_size) * sizeof(*ptr));
- }
- events->events = ptr;
- events->alloc_size = new_size;
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Create epoll set and allocate returned events structure.
- */
-int compat_epoll_create(struct lttng_poll_event *events, int size, int flags)
-{
- int ret;
-
- if (events == NULL || size <= 0) {
- goto error;
- }
-
- if (!poll_max_size) {
- if (lttng_poll_set_max_size()) {
- goto error;
- }
- }
-
- /* Don't bust the limit here */
- if (size > poll_max_size) {
- size = poll_max_size;
- }
-
- ret = compat_glibc_epoll_create(size, flags);
- if (ret < 0) {
- /* At this point, every error is fatal */
- PERROR("epoll_create1");
- goto error;
- }
-
- events->epfd = ret;
-
- /* This *must* be freed by using lttng_poll_free() */
- events->events = zmalloc(size * sizeof(struct epoll_event));
- if (events->events == NULL) {
- PERROR("zmalloc epoll set");
- goto error_close;
- }
-
- events->alloc_size = events->init_size = size;
- events->nb_fd = 0;
-
- return 0;
-
-error_close:
- ret = close(events->epfd);
- if (ret) {
- PERROR("close");
- }
-error:
- return -1;
-}
-
-/*
- * Add a fd to the epoll set with requesting events.
- */
-int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
-{
- int ret;
- struct epoll_event ev;
-
- if (events == NULL || events->events == NULL || fd < 0) {
- ERR("Bad compat epoll add arguments");
- goto error;
- }
-
- /*
- * Zero struct epoll_event to ensure all representations of its
- * union are zeroed.
- */
- memset(&ev, 0, sizeof(ev));
- ev.events = req_events;
- ev.data.fd = fd;
-
- ret = epoll_ctl(events->epfd, EPOLL_CTL_ADD, fd, &ev);
- if (ret < 0) {
- switch (errno) {
- case EEXIST:
- /* If exist, it's OK. */
- goto end;
- case ENOSPC:
- case EPERM:
- /* Print PERROR and goto end not failing. Show must go on. */
- PERROR("epoll_ctl ADD");
- goto end;
- default:
- PERROR("epoll_ctl ADD fatal");
- goto error;
- }
- }
-
- events->nb_fd++;
-
-end:
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Remove a fd from the epoll set.
- */
-int compat_epoll_del(struct lttng_poll_event *events, int fd)
-{
- int ret;
-
- if (events == NULL || fd < 0 || events->nb_fd == 0) {
- goto error;
- }
-
- ret = epoll_ctl(events->epfd, EPOLL_CTL_DEL, fd, NULL);
- if (ret < 0) {
- switch (errno) {
- case ENOENT:
- case EPERM:
- /* Print PERROR and goto end not failing. Show must go on. */
- PERROR("epoll_ctl DEL");
- goto end;
- default:
- PERROR("epoll_ctl DEL fatal");
- goto error;
- }
- }
-
- events->nb_fd--;
-
-end:
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Set an fd's events.
- */
-int compat_epoll_mod(struct lttng_poll_event *events, int fd, uint32_t req_events)
-{
- int ret;
- struct epoll_event ev;
-
- if (events == NULL || fd < 0 || events->nb_fd == 0) {
- goto error;
- }
-
- /*
- * Zero struct epoll_event to ensure all representations of its
- * union are zeroed.
- */
- memset(&ev, 0, sizeof(ev));
- ev.events = req_events;
- ev.data.fd = fd;
-
- ret = epoll_ctl(events->epfd, EPOLL_CTL_MOD, fd, &ev);
- if (ret < 0) {
- switch (errno) {
- case ENOENT:
- case EPERM:
- /* Print PERROR and goto end not failing. Show must go on. */
- PERROR("epoll_ctl MOD");
- goto end;
- default:
- PERROR("epoll_ctl MOD fatal");
- goto error;
- }
- }
-
-end:
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Wait on epoll set. This is a blocking call of timeout value.
- */
-int compat_epoll_wait(struct lttng_poll_event *events, int timeout,
- bool interruptible)
-{
- int ret;
- uint32_t new_size;
-
- if (events == NULL || events->events == NULL) {
- ERR("Wrong arguments in compat_epoll_wait");
- goto error;
- }
-
- if (events->nb_fd == 0) {
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Resize if needed before waiting. We could either expand the array or
- * shrink it down. It's important to note that after this step, we are
- * ensured that the events argument of the epoll_wait call will be large
- * enough to hold every possible returned events.
- */
- new_size = 1U << utils_get_count_order_u32(events->nb_fd);
- if (new_size != events->alloc_size && new_size >= events->init_size) {
- ret = resize_poll_event(events, new_size);
- if (ret < 0) {
- /* ENOMEM problem at this point. */
- goto error;
- }
- }
-
- do {
- ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
- } while (!interruptible && ret == -1 && errno == EINTR);
- if (ret < 0) {
- if (errno != EINTR) {
- PERROR("epoll_wait");
- }
- goto error;
- }
-
- /*
- * Since the returned events are set sequentially in the "events" structure
- * we only need to return the epoll_wait value and iterate over it.
- */
- return ret;
-
-error:
- return -1;
-}
-
-/*
- * Setup poll set maximum size.
- */
-int compat_epoll_set_max_size(void)
-{
- int ret, fd, retval = 0;
- ssize_t size_ret;
- char buf[64];
-
- fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
- if (fd < 0) {
- /*
- * Failing on opening [1] is not an error per see. [1] was
- * introduced in Linux 2.6.28 but epoll is available since
- * 2.5.44. Hence, goto end and set a default value without
- * setting an error return value.
- *
- * [1] /proc/sys/fs/epoll/max_user_watches
- */
- retval = 0;
- goto end;
- }
-
- size_ret = lttng_read(fd, buf, sizeof(buf));
- /*
- * Allow reading a file smaller than buf, but keep space for
- * final \0.
- */
- if (size_ret < 0 || size_ret >= sizeof(buf)) {
- PERROR("read set max size");
- retval = -1;
- goto end_read;
- }
- buf[size_ret] = '\0';
- poll_max_size = atoi(buf);
-end_read:
- ret = close(fd);
- if (ret) {
- PERROR("close");
- }
-end:
- if (!poll_max_size) {
- poll_max_size = DEFAULT_POLL_SIZE;
- }
- DBG("epoll set max size is %d", poll_max_size);
- return retval;
-}
-
-#else /* HAVE_EPOLL */
-
-#include <sys/resource.h>
-#include <sys/time.h>
-
-/*
- * Maximum number of fd we can monitor.
- *
- * For poll(2), the max fds must not exceed RLIMIT_NOFILE given by
- * getrlimit(2).
- */
-static unsigned int poll_max_size;
-
-/*
- * Resize the epoll events structure of the new size.
- *
- * Return 0 on success or else -1 with the current events pointer untouched.
- */
-static int resize_poll_event(struct compat_poll_event_array *array,
- uint32_t new_size)
-{
- struct pollfd *ptr;
-
- LTTNG_ASSERT(array);
-
- /* Refuse to resize the array more than the max size. */
- if (new_size > poll_max_size) {
- goto error;
- }
-
- ptr = realloc(array->events, new_size * sizeof(*ptr));
- if (ptr == NULL) {
- PERROR("realloc epoll add");
- goto error;
- }
- if (new_size > array->alloc_size) {
- /* Zero newly allocated memory */
- memset(ptr + array->alloc_size, 0,
- (new_size - array->alloc_size) * sizeof(*ptr));
- }
- array->events = ptr;
- array->alloc_size = new_size;
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Update events with the current events object.
- */
-static int update_current_events(struct lttng_poll_event *events)
-{
- int ret;
- struct compat_poll_event_array *current, *wait;
-
- LTTNG_ASSERT(events);
-
- current = &events->current;
- wait = &events->wait;
-
- wait->nb_fd = current->nb_fd;
- if (current->alloc_size != wait->alloc_size) {
- ret = resize_poll_event(wait, current->alloc_size);
- if (ret < 0) {
- goto error;
- }
- }
- memcpy(wait->events, current->events,
- current->nb_fd * sizeof(*current->events));
-
- /* Update is done. */
- events->need_update = 0;
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Create pollfd data structure.
- */
-int compat_poll_create(struct lttng_poll_event *events, int size)
-{
- struct compat_poll_event_array *current, *wait;
-
- if (events == NULL || size <= 0) {
- ERR("Wrong arguments for poll create");
- goto error;
- }
-
- if (!poll_max_size) {
- if (lttng_poll_set_max_size()) {
- goto error;
- }
- }
-
- /* Don't bust the limit here */
- if (size > poll_max_size) {
- size = poll_max_size;
- }
-
- /* Reset everything before begining the allocation. */
- memset(events, 0, sizeof(struct lttng_poll_event));
-
- current = &events->current;
- wait = &events->wait;
-
- /* This *must* be freed by using lttng_poll_free() */
- wait->events = zmalloc(size * sizeof(struct pollfd));
- if (wait->events == NULL) {
- PERROR("zmalloc struct pollfd");
- goto error;
- }
-
- wait->alloc_size = wait->init_size = size;
-
- current->events = zmalloc(size * sizeof(struct pollfd));
- if (current->events == NULL) {
- PERROR("zmalloc struct current pollfd");
- goto error;
- }
-
- current->alloc_size = current->init_size = size;
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Add fd to pollfd data structure with requested events.
- */
-int compat_poll_add(struct lttng_poll_event *events, int fd,
- uint32_t req_events)
-{
- int new_size, ret, i;
- struct compat_poll_event_array *current;
-
- if (events == NULL || events->current.events == NULL || fd < 0) {
- ERR("Bad compat poll add arguments");
- goto error;
- }
-
- current = &events->current;
-
- /* Check if fd we are trying to add is already there. */
- for (i = 0; i < current->nb_fd; i++) {
- if (current->events[i].fd == fd) {
- errno = EEXIST;
- goto error;
- }
- }
-
- /* Resize array if needed. */
- new_size = 1U << utils_get_count_order_u32(current->nb_fd + 1);
- if (new_size != current->alloc_size && new_size >= current->init_size) {
- ret = resize_poll_event(current, new_size);
- if (ret < 0) {
- goto error;
- }
- }
-
- current->events[current->nb_fd].fd = fd;
- current->events[current->nb_fd].events = req_events;
- current->nb_fd++;
- events->need_update = 1;
-
- DBG("fd %d of %d added to pollfd", fd, current->nb_fd);
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Modify an fd's events..
- */
-int compat_poll_mod(struct lttng_poll_event *events, int fd,
- uint32_t req_events)
-{
- int i;
- struct compat_poll_event_array *current;
-
- if (events == NULL || events->current.nb_fd == 0 ||
- events->current.events == NULL || fd < 0) {
- ERR("Bad compat poll mod arguments");
- goto error;
- }
-
- current = &events->current;
-
- for (i = 0; i < current->nb_fd; i++) {
- if (current->events[i].fd == fd) {
- current->events[i].events = req_events;
- events->need_update = 1;
- break;
- }
- }
-
- /*
- * The epoll flavor doesn't flag modifying a non-included FD as an
- * error.
- */
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Remove a fd from the pollfd structure.
- */
-int compat_poll_del(struct lttng_poll_event *events, int fd)
-{
- int i, count = 0, ret;
- uint32_t new_size;
- struct compat_poll_event_array *current;
-
- if (events == NULL || events->current.nb_fd == 0 ||
- events->current.events == NULL || fd < 0) {
- goto error;
- }
-
- /* Ease our life a bit. */
- current = &events->current;
-
- for (i = 0; i < current->nb_fd; i++) {
- /* Don't put back the fd we want to delete */
- if (current->events[i].fd != fd) {
- current->events[count].fd = current->events[i].fd;
- current->events[count].events = current->events[i].events;
- count++;
- }
- }
-
- /* The fd was not in our set, return no error as with epoll. */
- if (current->nb_fd == count) {
- goto end;
- }
-
- /* No fd duplicate should be ever added into array. */
- LTTNG_ASSERT(current->nb_fd - 1 == count);
- current->nb_fd = count;
-
- /* Resize array if needed. */
- new_size = 1U << utils_get_count_order_u32(current->nb_fd);
- if (new_size != current->alloc_size && new_size >= current->init_size
- && current->nb_fd != 0) {
- ret = resize_poll_event(current, new_size);
- if (ret < 0) {
- goto error;
- }
- }
-
- events->need_update = 1;
-
-end:
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Wait on poll() with timeout. Blocking call.
- */
-int compat_poll_wait(struct lttng_poll_event *events, int timeout,
- bool interruptible)
-{
- int ret, active_fd_count;
- size_t pos = 0, consecutive_entries = 0, non_idle_pos;
-
- if (events == NULL || events->current.events == NULL) {
- ERR("poll wait arguments error");
- goto error;
- }
-
- if (events->current.nb_fd == 0) {
- /* Return an invalid error to be consistent with epoll. */
- errno = EINVAL;
- events->wait.nb_fd = 0;
- goto error;
- }
-
- if (events->need_update) {
- ret = update_current_events(events);
- if (ret < 0) {
- errno = ENOMEM;
- goto error;
- }
- }
-
- do {
- ret = poll(events->wait.events, events->wait.nb_fd, timeout);
- } while (!interruptible && ret == -1 && errno == EINTR);
- if (ret < 0) {
- if (errno != EINTR) {
- PERROR("poll wait");
- }
- goto error;
- }
-
- active_fd_count = ret;
-
- /*
- * Move all active pollfd structs to the beginning of the
- * array to emulate compat-epoll behaviour.
- */
- if (active_fd_count == events->wait.nb_fd) {
- goto end;
- }
-
- while (consecutive_entries != active_fd_count) {
- struct pollfd *current = &events->wait.events[pos];
- struct pollfd idle_entry;
-
- if (current->revents != 0) {
- consecutive_entries++;
- pos++;
- continue;
- }
-
- non_idle_pos = pos;
-
- /* Look for next non-idle entry. */
- while (events->wait.events[++non_idle_pos].revents == 0);
-
- /* Swap idle and non-idle entries. */
- idle_entry = *current;
- *current = events->wait.events[non_idle_pos];
- events->wait.events[non_idle_pos] = idle_entry;
-
- consecutive_entries++;
- pos++;
- }
-end:
- return ret;
-
-error:
- return -1;
-}
-
-/*
- * Setup poll set maximum size.
- */
-int compat_poll_set_max_size(void)
-{
- int ret, retval = 0;
- struct rlimit lim;
-
- ret = getrlimit(RLIMIT_NOFILE, &lim);
- if (ret < 0) {
- PERROR("getrlimit poll RLIMIT_NOFILE");
- retval = -1;
- goto end;
- }
-
- poll_max_size = lim.rlim_cur;
-end:
- if (poll_max_size == 0) {
- poll_max_size = DEFAULT_POLL_SIZE;
- }
- DBG("poll set max size set to %u", poll_max_size);
- return retval;
-}
-
-#endif /* !HAVE_EPOLL */
--- /dev/null
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <common/defaults.h>
+#include <common/error.h>
+#include <common/macros.h>
+#include <common/utils.h>
+
+#include "poll.h"
+
+#if HAVE_EPOLL
+
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/*
+ * Maximum number of fd we can monitor.
+ *
+ * For epoll(7), /proc/sys/fs/epoll/max_user_watches (since Linux 2.6.28) will
+ * be used for the maximum size of the poll set. If this interface is not
+ * available, according to the manpage, the max_user_watches value is 1/25 (4%)
+ * of the available low memory divided by the registration cost in bytes which
+ * is 90 bytes on a 32-bit kernel and 160 bytes on a 64-bit kernel.
+ *
+ */
+static unsigned int poll_max_size;
+
+/*
+ * Resize the epoll events structure of the new size.
+ *
+ * Return 0 on success or else -1 with the current events pointer untouched.
+ */
+static int resize_poll_event(struct lttng_poll_event *events,
+ uint32_t new_size)
+{
+ struct epoll_event *ptr;
+
+ LTTNG_ASSERT(events);
+
+ ptr = (epoll_event *) realloc(events->events, new_size * sizeof(*ptr));
+ if (ptr == NULL) {
+ PERROR("realloc epoll add");
+ goto error;
+ }
+ if (new_size > events->alloc_size) {
+ /* Zero newly allocated memory */
+ memset(ptr + events->alloc_size, 0,
+ (new_size - events->alloc_size) * sizeof(*ptr));
+ }
+ events->events = ptr;
+ events->alloc_size = new_size;
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Create epoll set and allocate returned events structure.
+ */
+int compat_epoll_create(struct lttng_poll_event *events, int size, int flags)
+{
+ int ret;
+
+ if (events == NULL || size <= 0) {
+ goto error;
+ }
+
+ if (!poll_max_size) {
+ if (lttng_poll_set_max_size()) {
+ goto error;
+ }
+ }
+
+ /* Don't bust the limit here */
+ if (size > poll_max_size) {
+ size = poll_max_size;
+ }
+
+ ret = compat_glibc_epoll_create(size, flags);
+ if (ret < 0) {
+ /* At this point, every error is fatal */
+ PERROR("epoll_create1");
+ goto error;
+ }
+
+ events->epfd = ret;
+
+ /* This *must* be freed by using lttng_poll_free() */
+ events->events = (epoll_event *) zmalloc(size * sizeof(struct epoll_event));
+ if (events->events == NULL) {
+ PERROR("zmalloc epoll set");
+ goto error_close;
+ }
+
+ events->alloc_size = events->init_size = size;
+ events->nb_fd = 0;
+
+ return 0;
+
+error_close:
+ ret = close(events->epfd);
+ if (ret) {
+ PERROR("close");
+ }
+error:
+ return -1;
+}
+
+/*
+ * Add a fd to the epoll set with requesting events.
+ */
+int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
+{
+ int ret;
+ struct epoll_event ev;
+
+ if (events == NULL || events->events == NULL || fd < 0) {
+ ERR("Bad compat epoll add arguments");
+ goto error;
+ }
+
+ /*
+ * Zero struct epoll_event to ensure all representations of its
+ * union are zeroed.
+ */
+ memset(&ev, 0, sizeof(ev));
+ ev.events = req_events;
+ ev.data.fd = fd;
+
+ ret = epoll_ctl(events->epfd, EPOLL_CTL_ADD, fd, &ev);
+ if (ret < 0) {
+ switch (errno) {
+ case EEXIST:
+ /* If exist, it's OK. */
+ goto end;
+ case ENOSPC:
+ case EPERM:
+ /* Print PERROR and goto end not failing. Show must go on. */
+ PERROR("epoll_ctl ADD");
+ goto end;
+ default:
+ PERROR("epoll_ctl ADD fatal");
+ goto error;
+ }
+ }
+
+ events->nb_fd++;
+
+end:
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Remove a fd from the epoll set.
+ */
+int compat_epoll_del(struct lttng_poll_event *events, int fd)
+{
+ int ret;
+
+ if (events == NULL || fd < 0 || events->nb_fd == 0) {
+ goto error;
+ }
+
+ ret = epoll_ctl(events->epfd, EPOLL_CTL_DEL, fd, NULL);
+ if (ret < 0) {
+ switch (errno) {
+ case ENOENT:
+ case EPERM:
+ /* Print PERROR and goto end not failing. Show must go on. */
+ PERROR("epoll_ctl DEL");
+ goto end;
+ default:
+ PERROR("epoll_ctl DEL fatal");
+ goto error;
+ }
+ }
+
+ events->nb_fd--;
+
+end:
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Set an fd's events.
+ */
+int compat_epoll_mod(struct lttng_poll_event *events, int fd, uint32_t req_events)
+{
+ int ret;
+ struct epoll_event ev;
+
+ if (events == NULL || fd < 0 || events->nb_fd == 0) {
+ goto error;
+ }
+
+ /*
+ * Zero struct epoll_event to ensure all representations of its
+ * union are zeroed.
+ */
+ memset(&ev, 0, sizeof(ev));
+ ev.events = req_events;
+ ev.data.fd = fd;
+
+ ret = epoll_ctl(events->epfd, EPOLL_CTL_MOD, fd, &ev);
+ if (ret < 0) {
+ switch (errno) {
+ case ENOENT:
+ case EPERM:
+ /* Print PERROR and goto end not failing. Show must go on. */
+ PERROR("epoll_ctl MOD");
+ goto end;
+ default:
+ PERROR("epoll_ctl MOD fatal");
+ goto error;
+ }
+ }
+
+end:
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Wait on epoll set. This is a blocking call of timeout value.
+ */
+int compat_epoll_wait(struct lttng_poll_event *events, int timeout,
+ bool interruptible)
+{
+ int ret;
+ uint32_t new_size;
+
+ if (events == NULL || events->events == NULL) {
+ ERR("Wrong arguments in compat_epoll_wait");
+ goto error;
+ }
+
+ if (events->nb_fd == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Resize if needed before waiting. We could either expand the array or
+ * shrink it down. It's important to note that after this step, we are
+ * ensured that the events argument of the epoll_wait call will be large
+ * enough to hold every possible returned events.
+ */
+ new_size = 1U << utils_get_count_order_u32(events->nb_fd);
+ if (new_size != events->alloc_size && new_size >= events->init_size) {
+ ret = resize_poll_event(events, new_size);
+ if (ret < 0) {
+ /* ENOMEM problem at this point. */
+ goto error;
+ }
+ }
+
+ do {
+ ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
+ } while (!interruptible && ret == -1 && errno == EINTR);
+ if (ret < 0) {
+ if (errno != EINTR) {
+ PERROR("epoll_wait");
+ }
+ goto error;
+ }
+
+ /*
+ * Since the returned events are set sequentially in the "events" structure
+ * we only need to return the epoll_wait value and iterate over it.
+ */
+ return ret;
+
+error:
+ return -1;
+}
+
+/*
+ * Setup poll set maximum size.
+ */
+int compat_epoll_set_max_size(void)
+{
+ int ret, fd, retval = 0;
+ ssize_t size_ret;
+ char buf[64];
+
+ fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
+ if (fd < 0) {
+ /*
+ * Failing on opening [1] is not an error per see. [1] was
+ * introduced in Linux 2.6.28 but epoll is available since
+ * 2.5.44. Hence, goto end and set a default value without
+ * setting an error return value.
+ *
+ * [1] /proc/sys/fs/epoll/max_user_watches
+ */
+ retval = 0;
+ goto end;
+ }
+
+ size_ret = lttng_read(fd, buf, sizeof(buf));
+ /*
+ * Allow reading a file smaller than buf, but keep space for
+ * final \0.
+ */
+ if (size_ret < 0 || size_ret >= sizeof(buf)) {
+ PERROR("read set max size");
+ retval = -1;
+ goto end_read;
+ }
+ buf[size_ret] = '\0';
+ poll_max_size = atoi(buf);
+end_read:
+ ret = close(fd);
+ if (ret) {
+ PERROR("close");
+ }
+end:
+ if (!poll_max_size) {
+ poll_max_size = DEFAULT_POLL_SIZE;
+ }
+ DBG("epoll set max size is %d", poll_max_size);
+ return retval;
+}
+
+#else /* HAVE_EPOLL */
+
+#include <sys/resource.h>
+#include <sys/time.h>
+
+/*
+ * Maximum number of fd we can monitor.
+ *
+ * For poll(2), the max fds must not exceed RLIMIT_NOFILE given by
+ * getrlimit(2).
+ */
+static unsigned int poll_max_size;
+
+/*
+ * Resize the epoll events structure of the new size.
+ *
+ * Return 0 on success or else -1 with the current events pointer untouched.
+ */
+static int resize_poll_event(struct compat_poll_event_array *array,
+ uint32_t new_size)
+{
+ struct pollfd *ptr;
+
+ LTTNG_ASSERT(array);
+
+ /* Refuse to resize the array more than the max size. */
+ if (new_size > poll_max_size) {
+ goto error;
+ }
+
+ ptr = realloc(array->events, new_size * sizeof(*ptr));
+ if (ptr == NULL) {
+ PERROR("realloc epoll add");
+ goto error;
+ }
+ if (new_size > array->alloc_size) {
+ /* Zero newly allocated memory */
+ memset(ptr + array->alloc_size, 0,
+ (new_size - array->alloc_size) * sizeof(*ptr));
+ }
+ array->events = ptr;
+ array->alloc_size = new_size;
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Update events with the current events object.
+ */
+static int update_current_events(struct lttng_poll_event *events)
+{
+ int ret;
+ struct compat_poll_event_array *current, *wait;
+
+ LTTNG_ASSERT(events);
+
+ current = &events->current;
+ wait = &events->wait;
+
+ wait->nb_fd = current->nb_fd;
+ if (current->alloc_size != wait->alloc_size) {
+ ret = resize_poll_event(wait, current->alloc_size);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+ memcpy(wait->events, current->events,
+ current->nb_fd * sizeof(*current->events));
+
+ /* Update is done. */
+ events->need_update = 0;
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Create pollfd data structure.
+ */
+int compat_poll_create(struct lttng_poll_event *events, int size)
+{
+ struct compat_poll_event_array *current, *wait;
+
+ if (events == NULL || size <= 0) {
+ ERR("Wrong arguments for poll create");
+ goto error;
+ }
+
+ if (!poll_max_size) {
+ if (lttng_poll_set_max_size()) {
+ goto error;
+ }
+ }
+
+ /* Don't bust the limit here */
+ if (size > poll_max_size) {
+ size = poll_max_size;
+ }
+
+ /* Reset everything before begining the allocation. */
+ memset(events, 0, sizeof(struct lttng_poll_event));
+
+ current = &events->current;
+ wait = &events->wait;
+
+ /* This *must* be freed by using lttng_poll_free() */
+ wait->events = zmalloc(size * sizeof(struct pollfd));
+ if (wait->events == NULL) {
+ PERROR("zmalloc struct pollfd");
+ goto error;
+ }
+
+ wait->alloc_size = wait->init_size = size;
+
+ current->events = zmalloc(size * sizeof(struct pollfd));
+ if (current->events == NULL) {
+ PERROR("zmalloc struct current pollfd");
+ goto error;
+ }
+
+ current->alloc_size = current->init_size = size;
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Add fd to pollfd data structure with requested events.
+ */
+int compat_poll_add(struct lttng_poll_event *events, int fd,
+ uint32_t req_events)
+{
+ int new_size, ret, i;
+ struct compat_poll_event_array *current;
+
+ if (events == NULL || events->current.events == NULL || fd < 0) {
+ ERR("Bad compat poll add arguments");
+ goto error;
+ }
+
+ current = &events->current;
+
+ /* Check if fd we are trying to add is already there. */
+ for (i = 0; i < current->nb_fd; i++) {
+ if (current->events[i].fd == fd) {
+ errno = EEXIST;
+ goto error;
+ }
+ }
+
+ /* Resize array if needed. */
+ new_size = 1U << utils_get_count_order_u32(current->nb_fd + 1);
+ if (new_size != current->alloc_size && new_size >= current->init_size) {
+ ret = resize_poll_event(current, new_size);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+
+ current->events[current->nb_fd].fd = fd;
+ current->events[current->nb_fd].events = req_events;
+ current->nb_fd++;
+ events->need_update = 1;
+
+ DBG("fd %d of %d added to pollfd", fd, current->nb_fd);
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Modify an fd's events..
+ */
+int compat_poll_mod(struct lttng_poll_event *events, int fd,
+ uint32_t req_events)
+{
+ int i;
+ struct compat_poll_event_array *current;
+
+ if (events == NULL || events->current.nb_fd == 0 ||
+ events->current.events == NULL || fd < 0) {
+ ERR("Bad compat poll mod arguments");
+ goto error;
+ }
+
+ current = &events->current;
+
+ for (i = 0; i < current->nb_fd; i++) {
+ if (current->events[i].fd == fd) {
+ current->events[i].events = req_events;
+ events->need_update = 1;
+ break;
+ }
+ }
+
+ /*
+ * The epoll flavor doesn't flag modifying a non-included FD as an
+ * error.
+ */
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Remove a fd from the pollfd structure.
+ */
+int compat_poll_del(struct lttng_poll_event *events, int fd)
+{
+ int i, count = 0, ret;
+ uint32_t new_size;
+ struct compat_poll_event_array *current;
+
+ if (events == NULL || events->current.nb_fd == 0 ||
+ events->current.events == NULL || fd < 0) {
+ goto error;
+ }
+
+ /* Ease our life a bit. */
+ current = &events->current;
+
+ for (i = 0; i < current->nb_fd; i++) {
+ /* Don't put back the fd we want to delete */
+ if (current->events[i].fd != fd) {
+ current->events[count].fd = current->events[i].fd;
+ current->events[count].events = current->events[i].events;
+ count++;
+ }
+ }
+
+ /* The fd was not in our set, return no error as with epoll. */
+ if (current->nb_fd == count) {
+ goto end;
+ }
+
+ /* No fd duplicate should be ever added into array. */
+ LTTNG_ASSERT(current->nb_fd - 1 == count);
+ current->nb_fd = count;
+
+ /* Resize array if needed. */
+ new_size = 1U << utils_get_count_order_u32(current->nb_fd);
+ if (new_size != current->alloc_size && new_size >= current->init_size
+ && current->nb_fd != 0) {
+ ret = resize_poll_event(current, new_size);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+
+ events->need_update = 1;
+
+end:
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Wait on poll() with timeout. Blocking call.
+ */
+int compat_poll_wait(struct lttng_poll_event *events, int timeout,
+ bool interruptible)
+{
+ int ret, active_fd_count;
+ size_t pos = 0, consecutive_entries = 0, non_idle_pos;
+
+ if (events == NULL || events->current.events == NULL) {
+ ERR("poll wait arguments error");
+ goto error;
+ }
+
+ if (events->current.nb_fd == 0) {
+ /* Return an invalid error to be consistent with epoll. */
+ errno = EINVAL;
+ events->wait.nb_fd = 0;
+ goto error;
+ }
+
+ if (events->need_update) {
+ ret = update_current_events(events);
+ if (ret < 0) {
+ errno = ENOMEM;
+ goto error;
+ }
+ }
+
+ do {
+ ret = poll(events->wait.events, events->wait.nb_fd, timeout);
+ } while (!interruptible && ret == -1 && errno == EINTR);
+ if (ret < 0) {
+ if (errno != EINTR) {
+ PERROR("poll wait");
+ }
+ goto error;
+ }
+
+ active_fd_count = ret;
+
+ /*
+ * Move all active pollfd structs to the beginning of the
+ * array to emulate compat-epoll behaviour.
+ */
+ if (active_fd_count == events->wait.nb_fd) {
+ goto end;
+ }
+
+ while (consecutive_entries != active_fd_count) {
+ struct pollfd *current = &events->wait.events[pos];
+ struct pollfd idle_entry;
+
+ if (current->revents != 0) {
+ consecutive_entries++;
+ pos++;
+ continue;
+ }
+
+ non_idle_pos = pos;
+
+ /* Look for next non-idle entry. */
+ while (events->wait.events[++non_idle_pos].revents == 0);
+
+ /* Swap idle and non-idle entries. */
+ idle_entry = *current;
+ *current = events->wait.events[non_idle_pos];
+ events->wait.events[non_idle_pos] = idle_entry;
+
+ consecutive_entries++;
+ pos++;
+ }
+end:
+ return ret;
+
+error:
+ return -1;
+}
+
+/*
+ * Setup poll set maximum size.
+ */
+int compat_poll_set_max_size(void)
+{
+ int ret, retval = 0;
+ struct rlimit lim;
+
+ ret = getrlimit(RLIMIT_NOFILE, &lim);
+ if (ret < 0) {
+ PERROR("getrlimit poll RLIMIT_NOFILE");
+ retval = -1;
+ goto end;
+ }
+
+ poll_max_size = lim.rlim_cur;
+end:
+ if (poll_max_size == 0) {
+ poll_max_size = DEFAULT_POLL_SIZE;
+ }
+ DBG("poll set max size set to %u", poll_max_size);
+ return retval;
+}
+
+#endif /* !HAVE_EPOLL */
+++ /dev/null
-/*
- * filter-grammar-test.c
- *
- * LTTng filter grammar test
- *
- * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include <common/compat/errno.h>
-#include <common/bytecode/bytecode.h>
-#include <common/filter/filter-ast.h>
-#include <common/filter/filter-parser.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-int main(int argc, char **argv)
-{
- struct filter_parser_ctx *ctx;
- int ret;
- int print_xml = 0, generate_ir = 0, generate_bytecode = 0,
- print_bytecode = 0;
- int argidx;
-
- for (argidx = 1; argidx < argc; argidx++) {
- if (strcmp(argv[argidx], "-p") == 0)
- print_xml = 1;
- else if (strcmp(argv[argidx], "-i") == 0)
- generate_ir = 1;
- else if (strcmp(argv[argidx], "-b") == 0)
- generate_bytecode = 1;
- else if (strcmp(argv[argidx], "-d") == 0)
- filter_parser_debug = 1;
- else if (strcmp(argv[argidx], "-B") == 0)
- print_bytecode = 1;
- }
-
- /*
- * Force generate the bytecode if the user asks to print the bytecode
- * (can't print it without generating it first).
- */
- if (print_bytecode) {
- generate_bytecode = 1;
- }
-
- /*
- * Force generate the IR if the user asks to generate the bytecode
- * (the bytecode is generated by visiting the IR).
- */
- if (generate_bytecode) {
- generate_ir = 1;
- }
-
- ctx = filter_parser_ctx_alloc(stdin);
- if (!ctx) {
- fprintf(stderr, "Error allocating parser\n");
- goto alloc_error;
- }
- ret = filter_parser_ctx_append_ast(ctx);
- if (ret) {
- fprintf(stderr, "Parse error\n");
- goto parse_error;
- }
- if (print_xml) {
- ret = filter_visitor_print_xml(ctx, stdout, 0);
- if (ret) {
- fflush(stdout);
- fprintf(stderr, "XML print error\n");
- goto parse_error;
- }
- }
- if (generate_ir) {
- printf("Generating IR... ");
- fflush(stdout);
- ret = filter_visitor_ir_generate(ctx);
- if (ret) {
- fprintf(stderr, "Generate IR error\n");
- goto parse_error;
- }
- printf("done\n");
-
- printf("Validating IR... ");
- fflush(stdout);
- ret = filter_visitor_ir_check_binary_op_nesting(ctx);
- if (ret) {
- goto parse_error;
- }
- printf("done\n");
- }
- if (generate_bytecode) {
- printf("Generating bytecode... ");
- fflush(stdout);
- ret = filter_visitor_bytecode_generate(ctx);
- if (ret) {
- fprintf(stderr, "Generate bytecode error\n");
- goto parse_error;
- }
- printf("done\n");
- printf("Size of bytecode generated: %u bytes.\n",
- bytecode_get_len(&ctx->bytecode->b));
- }
-
- if (print_bytecode) {
- unsigned int bytecode_len, len, i;
-
- len = bytecode_get_len(&ctx->bytecode->b);
- bytecode_len = ctx->bytecode->b.reloc_table_offset;
- printf("Bytecode:\n");
- for (i = 0; i < bytecode_len; i++) {
- printf("0x%X ",
- ((uint8_t *) ctx->bytecode->b.data)[i]);
- }
- printf("\n");
- printf("Reloc table:\n");
- for (i = bytecode_len; i < len;) {
- printf("{ 0x%X, ",
- *(uint16_t *) &ctx->bytecode->b.data[i]);
- i += sizeof(uint16_t);
- printf("%s } ", &((char *) ctx->bytecode->b.data)[i]);
- i += strlen(&((char *) ctx->bytecode->b.data)[i]) + 1;
- }
- printf("\n");
- }
-
- filter_bytecode_free(ctx);
- filter_ir_free(ctx);
- filter_parser_ctx_free(ctx);
- return 0;
-
-parse_error:
- filter_bytecode_free(ctx);
- filter_ir_free(ctx);
- filter_parser_ctx_free(ctx);
-alloc_error:
- exit(EXIT_FAILURE);
-}
--- /dev/null
+/*
+ * filter-grammar-test.c
+ *
+ * LTTng filter grammar test
+ *
+ * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include <common/compat/errno.h>
+#include <common/bytecode/bytecode.h>
+#include <common/filter/filter-ast.h>
+#include <common/filter/filter-parser.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+int main(int argc, char **argv)
+{
+ struct filter_parser_ctx *ctx;
+ int ret;
+ int print_xml = 0, generate_ir = 0, generate_bytecode = 0,
+ print_bytecode = 0;
+ int argidx;
+
+ for (argidx = 1; argidx < argc; argidx++) {
+ if (strcmp(argv[argidx], "-p") == 0)
+ print_xml = 1;
+ else if (strcmp(argv[argidx], "-i") == 0)
+ generate_ir = 1;
+ else if (strcmp(argv[argidx], "-b") == 0)
+ generate_bytecode = 1;
+ else if (strcmp(argv[argidx], "-d") == 0)
+ filter_parser_debug = 1;
+ else if (strcmp(argv[argidx], "-B") == 0)
+ print_bytecode = 1;
+ }
+
+ /*
+ * Force generate the bytecode if the user asks to print the bytecode
+ * (can't print it without generating it first).
+ */
+ if (print_bytecode) {
+ generate_bytecode = 1;
+ }
+
+ /*
+ * Force generate the IR if the user asks to generate the bytecode
+ * (the bytecode is generated by visiting the IR).
+ */
+ if (generate_bytecode) {
+ generate_ir = 1;
+ }
+
+ ctx = filter_parser_ctx_alloc(stdin);
+ if (!ctx) {
+ fprintf(stderr, "Error allocating parser\n");
+ goto alloc_error;
+ }
+ ret = filter_parser_ctx_append_ast(ctx);
+ if (ret) {
+ fprintf(stderr, "Parse error\n");
+ goto parse_error;
+ }
+ if (print_xml) {
+ ret = filter_visitor_print_xml(ctx, stdout, 0);
+ if (ret) {
+ fflush(stdout);
+ fprintf(stderr, "XML print error\n");
+ goto parse_error;
+ }
+ }
+ if (generate_ir) {
+ printf("Generating IR... ");
+ fflush(stdout);
+ ret = filter_visitor_ir_generate(ctx);
+ if (ret) {
+ fprintf(stderr, "Generate IR error\n");
+ goto parse_error;
+ }
+ printf("done\n");
+
+ printf("Validating IR... ");
+ fflush(stdout);
+ ret = filter_visitor_ir_check_binary_op_nesting(ctx);
+ if (ret) {
+ goto parse_error;
+ }
+ printf("done\n");
+ }
+ if (generate_bytecode) {
+ printf("Generating bytecode... ");
+ fflush(stdout);
+ ret = filter_visitor_bytecode_generate(ctx);
+ if (ret) {
+ fprintf(stderr, "Generate bytecode error\n");
+ goto parse_error;
+ }
+ printf("done\n");
+ printf("Size of bytecode generated: %u bytes.\n",
+ bytecode_get_len(&ctx->bytecode->b));
+ }
+
+ if (print_bytecode) {
+ unsigned int bytecode_len, len, i;
+
+ len = bytecode_get_len(&ctx->bytecode->b);
+ bytecode_len = ctx->bytecode->b.reloc_table_offset;
+ printf("Bytecode:\n");
+ for (i = 0; i < bytecode_len; i++) {
+ printf("0x%X ",
+ ((uint8_t *) ctx->bytecode->b.data)[i]);
+ }
+ printf("\n");
+ printf("Reloc table:\n");
+ for (i = bytecode_len; i < len;) {
+ printf("{ 0x%X, ",
+ *(uint16_t *) &ctx->bytecode->b.data[i]);
+ i += sizeof(uint16_t);
+ printf("%s } ", &((char *) ctx->bytecode->b.data)[i]);
+ i += strlen(&((char *) ctx->bytecode->b.data)[i]) + 1;
+ }
+ printf("\n");
+ }
+
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+ return 0;
+
+parse_error:
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+alloc_error:
+ exit(EXIT_FAILURE);
+}
endif
# URI unit tests
-test_uri_SOURCES = test_uri.c
+test_uri_SOURCES = test_uri.cpp
test_uri_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBHASHTABLE) $(DL_LIBS)
RELAYD_OBJS = $(top_builddir)/src/bin/lttng-relayd/backward-compatibility-group-by.$(OBJEXT)
# utils suffix for unit test
# parse_size_suffix unit test
-test_utils_parse_size_suffix_SOURCES = test_utils_parse_size_suffix.c
+test_utils_parse_size_suffix_SOURCES = test_utils_parse_size_suffix.cpp
test_utils_parse_size_suffix_LDADD = $(LIBTAP) $(LIBHASHTABLE) $(LIBCOMMON) $(DL_LIBS)
# parse_time_suffix unit test
-test_utils_parse_time_suffix_SOURCES = test_utils_parse_time_suffix.c
+test_utils_parse_time_suffix_SOURCES = test_utils_parse_time_suffix.cpp
test_utils_parse_time_suffix_LDADD = $(LIBTAP) $(LIBHASHTABLE) $(LIBCOMMON)
# compat_poll unit test
-test_utils_compat_poll_SOURCES = test_utils_compat_poll.c
+test_utils_compat_poll_SOURCES = test_utils_compat_poll.cpp
test_utils_compat_poll_LDADD = $(LIBTAP) $(LIBHASHTABLE) $(DL_LIBS) \
$(top_builddir)/src/common/compat/libcompat.la $(LIBCOMMON)
# compat_pthread unit test
-test_utils_compat_pthread_SOURCES = test_utils_compat_pthread.c
+test_utils_compat_pthread_SOURCES = test_utils_compat_pthread.cpp
test_utils_compat_pthread_LDADD = $(LIBTAP) \
$(top_builddir)/src/common/compat/libcompat.la $(LIBCOMMON)
# expand_path unit test
-test_utils_expand_path_SOURCES = test_utils_expand_path.c
+test_utils_expand_path_SOURCES = test_utils_expand_path.cpp
test_utils_expand_path_LDADD = $(LIBTAP) $(LIBHASHTABLE) $(LIBCOMMON) $(DL_LIBS)
# directory handle unit test
-test_directory_handle_SOURCES = test_directory_handle.c
+test_directory_handle_SOURCES = test_directory_handle.cpp
test_directory_handle_LDADD = $(LIBTAP) $(LIBHASHTABLE) $(LIBCOMMON) $(DL_LIBS)
# string utilities unit test
-test_string_utils_SOURCES = test_string_utils.c
+test_string_utils_SOURCES = test_string_utils.cpp
test_string_utils_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBSTRINGUTILS) $(DL_LIBS)
# Notification api
-test_notification_SOURCES = test_notification.c
+test_notification_SOURCES = test_notification.cpp
test_notification_LDADD = $(LIBTAP) $(LIBLTTNG_CTL) $(DL_LIBS)
# Event rule api
-test_event_rule_SOURCES = test_event_rule.c
+test_event_rule_SOURCES = test_event_rule.cpp
test_event_rule_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBLTTNG_CTL) $(DL_LIBS) \
$(top_builddir)/src/bin/lttng/lttng-loglevel.$(OBJEXT)
# Condition api
-test_condition_SOURCES = test_condition.c
+test_condition_SOURCES = test_condition.cpp
test_condition_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBLTTNG_CTL) $(DL_LIBS)
# relayd backward compat for groou-by-session utilities
test_relayd_backward_compat_group_by_session_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/bin/lttng-relayd
# rate policy object unit test
-test_rate_policy_SOURCES = test_rate_policy.c
+test_rate_policy_SOURCES = test_rate_policy.cpp
test_rate_policy_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBLTTNG_CTL) $(DL_LIBS) \
$(top_builddir)/src/bin/lttng/lttng-loglevel.$(OBJEXT)
# fd tracker unit test
-test_fd_tracker_SOURCES = test_fd_tracker.c
+test_fd_tracker_SOURCES = test_fd_tracker.cpp
test_fd_tracker_LDADD = $(LIBTAP) $(LIBFDTRACKER) $(DL_LIBS) $(URCU_LIBS) $(LIBCOMMON) $(LIBHASHTABLE)
# uuid unit test
-test_uuid_SOURCES = test_uuid.c
+test_uuid_SOURCES = test_uuid.cpp
test_uuid_LDADD = $(LIBTAP) $(LIBCOMMON)
# buffer view unit test
-test_buffer_view_SOURCES = test_buffer_view.c
+test_buffer_view_SOURCES = test_buffer_view.cpp
test_buffer_view_LDADD = $(LIBTAP) $(LIBCOMMON)
# payload unit test
-test_payload_SOURCES = test_payload.c
+test_payload_SOURCES = test_payload.cpp
test_payload_LDADD = $(LIBTAP) $(LIBSESSIOND_COMM) $(LIBCOMMON)
# unix socket test
-test_unix_socket_SOURCES = test_unix_socket.c
+test_unix_socket_SOURCES = test_unix_socket.cpp
test_unix_socket_LDADD = $(LIBTAP) $(LIBSESSIOND_COMM) $(LIBCOMMON)
# Kernel probe location api test
-test_kernel_probe_SOURCES = test_kernel_probe.c
+test_kernel_probe_SOURCES = test_kernel_probe.cpp
test_kernel_probe_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBLTTNG_CTL) $(DL_LIBS)
#
# Event expression to bytecode test
-test_event_expr_to_bytecode_SOURCES = test_event_expr_to_bytecode.c
+test_event_expr_to_bytecode_SOURCES = test_event_expr_to_bytecode.cpp
test_event_expr_to_bytecode_LDADD = $(LIBTAP) $(LIBLTTNG_CTL) $(LIBCOMMON)
# Log level rule api
-test_log_level_rule_SOURCES = test_log_level_rule.c
+test_log_level_rule_SOURCES = test_log_level_rule.cpp
test_log_level_rule_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBLTTNG_CTL) $(DL_LIBS)
# Action api
-test_action_SOURCES = test_action.c
+test_action_SOURCES = test_action.cpp
test_action_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBLTTNG_CTL) $(DL_LIBS)
noinst_PROGRAMS = ini_config
EXTRA_DIST = test_ini_config sample.ini
-ini_config_SOURCES = ini_config.c
+ini_config_SOURCES = ini_config.cpp
ini_config_LDADD = $(LIBTAP) $(LIBCONFIG) $(LIBCOMMON) $(LIBHASHTABLE) \
$(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la
+++ /dev/null
-/*
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <tap/tap.h>
-#include <common/config/session-config.h>
-#include <common/utils.h>
-#include <string.h>
-#include <lttng/constant.h>
-
-struct state {
- int section_1;
- int section_2;
- int section_3;
- int section_global;
- int text_entry;
- int int_entry;
-};
-
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose = 0;
-int lttng_opt_mi;
-
-static int entry_handler(const struct config_entry *entry, struct state *state)
-{
- int ret = 0;
-
- if (!entry || !state) {
- ret = -1;
- goto end;
- }
-
- if (!strcmp(entry->section, "section1")) {
- state->section_1 = 1;
- if (!strcmp(entry->name, "section1_entry") &&
- !strcmp(entry->value, "42")) {
- state->int_entry = 1;
- }
- }
-
- if (!strcmp(entry->section, "section2")) {
- state->section_2 = 1;
- }
-
- if (!strcmp(entry->section, "section 3")) {
- state->section_3 = 1;
- if (!strcmp(entry->name, "name with a space") &&
- !strcmp(entry->value, "another value")) {
- state->text_entry = 1;
- }
- }
-
- if (!strcmp(entry->section, "")) {
- state->section_global = 1;
- }
-end:
- return ret;
-}
-
-int main(int argc, char **argv)
-{
- char *path = NULL;
- int ret;
- struct state state = {};
-
- if (argc < 2) {
- diag("Usage: path_to_sample_INI_file");
- goto end;
- }
-
- if (strlen(argv[1]) >= LTTNG_PATH_MAX) {
- diag("The provided path exceeds the maximal permitted length of %i bytes",
- LTTNG_PATH_MAX);
- goto end;
- }
- path = utils_expand_path(argv[1]);
- if (!path) {
- fail("Failed to resolve sample INI file path");
- }
-
- plan_no_plan();
- ret = config_get_section_entries(path, NULL,
- (config_entry_handler_cb)entry_handler, &state);
- ok(ret == 0, "Successfully opened a config file, registered to all sections");
- ok(state.section_1 && state.section_2 && state.section_3 &&
- state.section_global, "Processed entries from each sections");
- ok(state.text_entry, "Text value parsed correctly");
-
- memset(&state, 0, sizeof(struct state));
- ret = config_get_section_entries(path, "section1",
- (config_entry_handler_cb)entry_handler, &state);
- ok(ret == 0, "Successfully opened a config file, registered to one section");
- ok(state.section_1 && !state.section_2 && !state.section_3 &&
- !state.section_global, "Processed an entry from section1 only");
- ok(state.int_entry, "Int value parsed correctly");
-
- memset(&state, 0, sizeof(struct state));
- ret = config_get_section_entries(path, "",
- (config_entry_handler_cb)entry_handler, &state);
- ok(ret == 0, "Successfully opened a config file, registered to the global section");
- ok(!state.section_1 && !state.section_2 && !state.section_3 &&
- state.section_global, "Processed an entry from the global section only");
-end:
- free(path);
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <tap/tap.h>
+#include <common/config/session-config.h>
+#include <common/utils.h>
+#include <string.h>
+#include <lttng/constant.h>
+
+struct state {
+ int section_1;
+ int section_2;
+ int section_3;
+ int section_global;
+ int text_entry;
+ int int_entry;
+};
+
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose = 0;
+int lttng_opt_mi;
+
+static int entry_handler(const struct config_entry *entry, struct state *state)
+{
+ int ret = 0;
+
+ if (!entry || !state) {
+ ret = -1;
+ goto end;
+ }
+
+ if (!strcmp(entry->section, "section1")) {
+ state->section_1 = 1;
+ if (!strcmp(entry->name, "section1_entry") &&
+ !strcmp(entry->value, "42")) {
+ state->int_entry = 1;
+ }
+ }
+
+ if (!strcmp(entry->section, "section2")) {
+ state->section_2 = 1;
+ }
+
+ if (!strcmp(entry->section, "section 3")) {
+ state->section_3 = 1;
+ if (!strcmp(entry->name, "name with a space") &&
+ !strcmp(entry->value, "another value")) {
+ state->text_entry = 1;
+ }
+ }
+
+ if (!strcmp(entry->section, "")) {
+ state->section_global = 1;
+ }
+end:
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ char *path = NULL;
+ int ret;
+ struct state state = {};
+
+ if (argc < 2) {
+ diag("Usage: path_to_sample_INI_file");
+ goto end;
+ }
+
+ if (strlen(argv[1]) >= LTTNG_PATH_MAX) {
+ diag("The provided path exceeds the maximal permitted length of %i bytes",
+ LTTNG_PATH_MAX);
+ goto end;
+ }
+ path = utils_expand_path(argv[1]);
+ if (!path) {
+ fail("Failed to resolve sample INI file path");
+ }
+
+ plan_no_plan();
+ ret = config_get_section_entries(path, NULL,
+ (config_entry_handler_cb)entry_handler, &state);
+ ok(ret == 0, "Successfully opened a config file, registered to all sections");
+ ok(state.section_1 && state.section_2 && state.section_3 &&
+ state.section_global, "Processed entries from each sections");
+ ok(state.text_entry, "Text value parsed correctly");
+
+ memset(&state, 0, sizeof(struct state));
+ ret = config_get_section_entries(path, "section1",
+ (config_entry_handler_cb)entry_handler, &state);
+ ok(ret == 0, "Successfully opened a config file, registered to one section");
+ ok(state.section_1 && !state.section_2 && !state.section_3 &&
+ !state.section_global, "Processed an entry from section1 only");
+ ok(state.int_entry, "Int value parsed correctly");
+
+ memset(&state, 0, sizeof(struct state));
+ ret = config_get_section_entries(path, "",
+ (config_entry_handler_cb)entry_handler, &state);
+ ok(ret == 0, "Successfully opened a config file, registered to the global section");
+ ok(!state.section_1 && !state.section_2 && !state.section_3 &&
+ state.section_global, "Processed an entry from the global section only");
+end:
+ free(path);
+ return exit_status();
+}
+++ /dev/null
-/*
- * test_action.c
- *
- * Unit tests for the notification API.
- *
- * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <tap/tap.h>
-
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/action.h>
-#include <lttng/action/notify.h>
-#include <lttng/action/rate-policy-internal.h>
-#include <lttng/action/rate-policy.h>
-#include <lttng/action/rotate-session.h>
-#include <lttng/action/snapshot-session.h>
-#include <lttng/action/start-session.h>
-#include <lttng/action/stop-session.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-#define NUM_TESTS 60
-
-static void test_action_notify(void)
-{
- int ret;
- enum lttng_action_status status;
- struct lttng_action *notify_action = NULL,
- *notify_action_from_buffer = NULL;
- struct lttng_rate_policy *policy = NULL, *default_policy;
- struct lttng_payload payload;
-
- lttng_payload_init(&payload);
-
- /* To set. */
- policy = lttng_rate_policy_every_n_create(100);
- /* For comparison. */
- default_policy = lttng_rate_policy_every_n_create(1);
-
- LTTNG_ASSERT(policy && default_policy);
-
- notify_action = lttng_action_notify_create();
- ok(notify_action, "Create notify action");
- ok(lttng_action_get_type(notify_action) == LTTNG_ACTION_TYPE_NOTIFY,
- "Action has type LTTNG_ACTION_TYPE_NOTIFY");
-
- /* Validate the default policy for a notify action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_notify_get_rate_policy(
- notify_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- default_policy,
- cur_policy),
- "Default policy is every n=1");
- }
-
- /* Set a custom policy. */
- status = lttng_action_notify_set_rate_policy(notify_action, policy);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
-
- /* Validate the custom policy for a notify action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_notify_get_rate_policy(
- notify_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- policy,
- cur_policy),
- "Notify action policy get");
- }
-
- ret = lttng_action_serialize(notify_action, &payload);
- ok(ret == 0, "Action notify serialized");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- (void) lttng_action_create_from_payload(
- &view, ¬ify_action_from_buffer);
- }
- ok(notify_action_from_buffer,
- "Notify action created from payload is non-null");
-
- ok(lttng_action_is_equal(notify_action, notify_action_from_buffer),
- "Serialized and de-serialized notify action are equal");
-
- lttng_rate_policy_destroy(default_policy);
- lttng_rate_policy_destroy(policy);
- lttng_action_destroy(notify_action);
- lttng_action_destroy(notify_action_from_buffer);
- lttng_payload_reset(&payload);
-}
-
-static void test_action_rotate_session(void)
-{
- int ret;
- enum lttng_action_status status;
- struct lttng_action *rotate_session_action = NULL,
- *rotate_session_action_from_buffer = NULL;
- struct lttng_rate_policy *policy = NULL, *default_policy;
- struct lttng_payload payload;
- const char *session_name = "my_session_name";
- const char *get_session_name;
-
- lttng_payload_init(&payload);
-
- /* To set. */
- policy = lttng_rate_policy_every_n_create(100);
- /* For comparison. */
- default_policy = lttng_rate_policy_every_n_create(1);
-
- LTTNG_ASSERT(policy && default_policy);
-
- rotate_session_action = lttng_action_rotate_session_create();
- ok(rotate_session_action, "Create rotate_session action");
- ok(lttng_action_get_type(rotate_session_action) ==
- LTTNG_ACTION_TYPE_ROTATE_SESSION,
- "Action has type LTTNG_ACTION_TYPE_ROTATE_SESSION");
-
- /* Session name setter. */
- status = lttng_action_rotate_session_set_session_name(NULL, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,NULL) expect invalid");
- status = lttng_action_rotate_session_set_session_name(
- rotate_session_action, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (object,NULL) expect invalid");
- status = lttng_action_rotate_session_set_session_name(
- NULL, session_name);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,object) expect invalid");
-
- /* Set the session name */
- status = lttng_action_rotate_session_set_session_name(
- rotate_session_action, session_name);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
-
- status = lttng_action_rotate_session_get_session_name(
- rotate_session_action, &get_session_name);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- !strcmp(session_name, get_session_name),
- "Get session name, expected `%s` got `%s`",
- session_name, get_session_name);
-
- /* Validate the default policy for a rotate_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_rotate_session_get_rate_policy(
- rotate_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- default_policy,
- cur_policy),
- "Default policy is every n=1");
- }
-
- /* Set a custom policy. */
- status = lttng_action_rotate_session_set_rate_policy(
- rotate_session_action, policy);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
-
- /* Validate the custom policy for a rotate_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_rotate_session_get_rate_policy(
- rotate_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- policy,
- cur_policy),
- "rotate_session action policy get");
- }
-
- /* Ser/des tests. */
- ret = lttng_action_serialize(rotate_session_action, &payload);
- ok(ret == 0, "Action rotate_session serialized");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- (void) lttng_action_create_from_payload(
- &view, &rotate_session_action_from_buffer);
- }
- ok(rotate_session_action_from_buffer,
- "rotate_session action created from payload is non-null");
-
- ok(lttng_action_is_equal(rotate_session_action,
- rotate_session_action_from_buffer),
- "Serialized and de-serialized rotate_session action are equal");
-
- lttng_rate_policy_destroy(default_policy);
- lttng_rate_policy_destroy(policy);
- lttng_action_destroy(rotate_session_action);
- lttng_action_destroy(rotate_session_action_from_buffer);
- lttng_payload_reset(&payload);
-}
-
-static void test_action_start_session(void)
-{
- int ret;
- enum lttng_action_status status;
- struct lttng_action *start_session_action = NULL,
- *start_session_action_from_buffer = NULL;
- struct lttng_rate_policy *policy = NULL, *default_policy;
- struct lttng_payload payload;
- const char *session_name = "my_session_name";
- const char *get_session_name;
-
- lttng_payload_init(&payload);
-
- /* To set. */
- policy = lttng_rate_policy_every_n_create(100);
- /* For comparison. */
- default_policy = lttng_rate_policy_every_n_create(1);
-
- LTTNG_ASSERT(policy && default_policy);
-
- start_session_action = lttng_action_start_session_create();
- ok(start_session_action, "Create start_session action");
- ok(lttng_action_get_type(start_session_action) ==
- LTTNG_ACTION_TYPE_START_SESSION,
- "Action has type LTTNG_ACTION_TYPE_START_SESSION");
-
- /* Session name setter. */
- status = lttng_action_start_session_set_session_name(NULL, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,NULL) expect invalid");
- status = lttng_action_start_session_set_session_name(
- start_session_action, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (object,NULL) expect invalid");
- status = lttng_action_start_session_set_session_name(
- NULL, session_name);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,object) expect invalid");
-
- /* Set the session name */
- status = lttng_action_start_session_set_session_name(
- start_session_action, session_name);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
-
- status = lttng_action_start_session_get_session_name(
- start_session_action, &get_session_name);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- !strcmp(session_name, get_session_name),
- "Get session name, expected `%s` got `%s`",
- session_name, get_session_name);
-
- /* Validate the default policy for a start_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_start_session_get_rate_policy(
- start_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- default_policy,
- cur_policy),
- "Default policy is every n=1");
- }
-
- /* Set a custom policy. */
- status = lttng_action_start_session_set_rate_policy(
- start_session_action, policy);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
-
- /* Validate the custom policy for a start_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_start_session_get_rate_policy(
- start_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- policy,
- cur_policy),
- "start_session action policy get");
- }
-
- /* Ser/des tests. */
- ret = lttng_action_serialize(start_session_action, &payload);
- ok(ret == 0, "Action start_session serialized");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- (void) lttng_action_create_from_payload(
- &view, &start_session_action_from_buffer);
- }
- ok(start_session_action_from_buffer,
- "start_session action created from payload is non-null");
-
- ok(lttng_action_is_equal(start_session_action,
- start_session_action_from_buffer),
- "Serialized and de-serialized start_session action are equal");
-
- lttng_rate_policy_destroy(default_policy);
- lttng_rate_policy_destroy(policy);
- lttng_action_destroy(start_session_action);
- lttng_action_destroy(start_session_action_from_buffer);
- lttng_payload_reset(&payload);
-}
-
-static void test_action_stop_session(void)
-{
- int ret;
- enum lttng_action_status status;
- struct lttng_action *stop_session_action = NULL,
- *stop_session_action_from_buffer = NULL;
- struct lttng_rate_policy *policy = NULL, *default_policy;
- struct lttng_payload payload;
- const char *session_name = "my_session_name";
- const char *get_session_name;
-
- lttng_payload_init(&payload);
-
- /* To set. */
- policy = lttng_rate_policy_every_n_create(100);
- /* For comparison. */
- default_policy = lttng_rate_policy_every_n_create(1);
-
- LTTNG_ASSERT(policy && default_policy);
-
- stop_session_action = lttng_action_stop_session_create();
- ok(stop_session_action, "Create stop_session action");
- ok(lttng_action_get_type(stop_session_action) ==
- LTTNG_ACTION_TYPE_STOP_SESSION,
- "Action has type LTTNG_ACTION_TYPE_STOP_SESSION");
-
- /* Session name setter. */
- status = lttng_action_stop_session_set_session_name(NULL, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,NULL) expect invalid");
- status = lttng_action_stop_session_set_session_name(
- stop_session_action, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (object,NULL) expect invalid");
- status = lttng_action_stop_session_set_session_name(NULL, session_name);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,object) expect invalid");
-
- /* Set the session name */
- status = lttng_action_stop_session_set_session_name(
- stop_session_action, session_name);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
-
- status = lttng_action_stop_session_get_session_name(
- stop_session_action, &get_session_name);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- !strcmp(session_name, get_session_name),
- "Get session name, expected `%s` got `%s`",
- session_name, get_session_name);
-
- /* Validate the default policy for a stop_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_stop_session_get_rate_policy(
- stop_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- default_policy,
- cur_policy),
- "Default policy is every n=1");
- }
-
- /* Set a custom policy. */
- status = lttng_action_stop_session_set_rate_policy(
- stop_session_action, policy);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
-
- /* Validate the custom policy for a stop_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_stop_session_get_rate_policy(
- stop_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- policy,
- cur_policy),
- "stop_session action policy get");
- }
-
- /* Ser/des tests. */
- ret = lttng_action_serialize(stop_session_action, &payload);
- ok(ret == 0, "Action stop_session serialized");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- (void) lttng_action_create_from_payload(
- &view, &stop_session_action_from_buffer);
- }
- ok(stop_session_action_from_buffer,
- "stop_session action created from payload is non-null");
-
- ok(lttng_action_is_equal(stop_session_action,
- stop_session_action_from_buffer),
- "Serialized and de-serialized stop_session action are equal");
-
- lttng_rate_policy_destroy(default_policy);
- lttng_rate_policy_destroy(policy);
- lttng_action_destroy(stop_session_action);
- lttng_action_destroy(stop_session_action_from_buffer);
- lttng_payload_reset(&payload);
-}
-
-static void test_action_snapshot_session(void)
-{
- int ret;
- enum lttng_action_status status;
- struct lttng_action *snapshot_session_action = NULL,
- *snapshot_session_action_from_buffer = NULL;
- struct lttng_rate_policy *policy = NULL, *default_policy;
- struct lttng_payload payload;
- const char *session_name = "my_session_name";
- const char *get_session_name;
-
- lttng_payload_init(&payload);
-
- /* To set. */
- policy = lttng_rate_policy_every_n_create(100);
- /* For comparison. */
- default_policy = lttng_rate_policy_every_n_create(1);
-
- LTTNG_ASSERT(policy && default_policy);
-
- snapshot_session_action = lttng_action_snapshot_session_create();
- ok(snapshot_session_action, "Create snapshot_session action");
- ok(lttng_action_get_type(snapshot_session_action) ==
- LTTNG_ACTION_TYPE_SNAPSHOT_SESSION,
- "Action has type LTTNG_ACTION_TYPE_SNAPSHOT_SESSION");
-
- /* Session name setter. */
- status = lttng_action_snapshot_session_set_session_name(NULL, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,NULL) expect invalid");
- status = lttng_action_snapshot_session_set_session_name(
- snapshot_session_action, NULL);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (object,NULL) expect invalid");
- status = lttng_action_snapshot_session_set_session_name(
- NULL, session_name);
- ok(status == LTTNG_ACTION_STATUS_INVALID,
- "Set session name (NULL,object) expect invalid");
-
- /* Set the session name */
- status = lttng_action_snapshot_session_set_session_name(
- snapshot_session_action, session_name);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
-
- status = lttng_action_snapshot_session_get_session_name(
- snapshot_session_action, &get_session_name);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- !strcmp(session_name, get_session_name),
- "Get session name, expected `%s` got `%s`",
- session_name, get_session_name);
-
- /* Validate the default policy for a snapshot_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_snapshot_session_get_rate_policy(
- snapshot_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- default_policy,
- cur_policy),
- "Default policy is every n=1");
- }
-
- /* Set a custom policy. */
- status = lttng_action_snapshot_session_set_rate_policy(
- snapshot_session_action, policy);
- ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
-
- /* Validate the custom policy for a snapshot_session action. */
- {
- const struct lttng_rate_policy *cur_policy = NULL;
- status = lttng_action_snapshot_session_get_rate_policy(
- snapshot_session_action, &cur_policy);
- ok(status == LTTNG_ACTION_STATUS_OK &&
- lttng_rate_policy_is_equal(
- policy,
- cur_policy),
- "snapshot_session action policy get");
- }
-
- /* Ser/des tests. */
- ret = lttng_action_serialize(snapshot_session_action, &payload);
- ok(ret == 0, "Action snapshot_session serialized");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- (void) lttng_action_create_from_payload(
- &view, &snapshot_session_action_from_buffer);
- }
- ok(snapshot_session_action_from_buffer,
- "snapshot_session action created from payload is non-null");
-
- ok(lttng_action_is_equal(snapshot_session_action,
- snapshot_session_action_from_buffer),
- "Serialized and de-serialized snapshot_session action are equal");
-
- lttng_rate_policy_destroy(default_policy);
- lttng_rate_policy_destroy(policy);
- lttng_action_destroy(snapshot_session_action);
- lttng_action_destroy(snapshot_session_action_from_buffer);
- lttng_payload_reset(&payload);
-}
-
-int main(int argc, const char *argv[])
-{
- plan_tests(NUM_TESTS);
- test_action_notify();
- test_action_rotate_session();
- test_action_start_session();
- test_action_stop_session();
- test_action_snapshot_session();
- return exit_status();
-}
--- /dev/null
+/*
+ * test_action.c
+ *
+ * Unit tests for the notification API.
+ *
+ * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/action/action-internal.h>
+#include <lttng/action/action.h>
+#include <lttng/action/notify.h>
+#include <lttng/action/rate-policy-internal.h>
+#include <lttng/action/rate-policy.h>
+#include <lttng/action/rotate-session.h>
+#include <lttng/action/snapshot-session.h>
+#include <lttng/action/start-session.h>
+#include <lttng/action/stop-session.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 60
+
+static void test_action_notify(void)
+{
+ int ret;
+ enum lttng_action_status status;
+ struct lttng_action *notify_action = NULL,
+ *notify_action_from_buffer = NULL;
+ struct lttng_rate_policy *policy = NULL, *default_policy;
+ struct lttng_payload payload;
+
+ lttng_payload_init(&payload);
+
+ /* To set. */
+ policy = lttng_rate_policy_every_n_create(100);
+ /* For comparison. */
+ default_policy = lttng_rate_policy_every_n_create(1);
+
+ LTTNG_ASSERT(policy && default_policy);
+
+ notify_action = lttng_action_notify_create();
+ ok(notify_action, "Create notify action");
+ ok(lttng_action_get_type(notify_action) == LTTNG_ACTION_TYPE_NOTIFY,
+ "Action has type LTTNG_ACTION_TYPE_NOTIFY");
+
+ /* Validate the default policy for a notify action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_notify_get_rate_policy(
+ notify_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ default_policy,
+ cur_policy),
+ "Default policy is every n=1");
+ }
+
+ /* Set a custom policy. */
+ status = lttng_action_notify_set_rate_policy(notify_action, policy);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
+
+ /* Validate the custom policy for a notify action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_notify_get_rate_policy(
+ notify_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ policy,
+ cur_policy),
+ "Notify action policy get");
+ }
+
+ ret = lttng_action_serialize(notify_action, &payload);
+ ok(ret == 0, "Action notify serialized");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ (void) lttng_action_create_from_payload(
+ &view, ¬ify_action_from_buffer);
+ }
+ ok(notify_action_from_buffer,
+ "Notify action created from payload is non-null");
+
+ ok(lttng_action_is_equal(notify_action, notify_action_from_buffer),
+ "Serialized and de-serialized notify action are equal");
+
+ lttng_rate_policy_destroy(default_policy);
+ lttng_rate_policy_destroy(policy);
+ lttng_action_destroy(notify_action);
+ lttng_action_destroy(notify_action_from_buffer);
+ lttng_payload_reset(&payload);
+}
+
+static void test_action_rotate_session(void)
+{
+ int ret;
+ enum lttng_action_status status;
+ struct lttng_action *rotate_session_action = NULL,
+ *rotate_session_action_from_buffer = NULL;
+ struct lttng_rate_policy *policy = NULL, *default_policy;
+ struct lttng_payload payload;
+ const char *session_name = "my_session_name";
+ const char *get_session_name;
+
+ lttng_payload_init(&payload);
+
+ /* To set. */
+ policy = lttng_rate_policy_every_n_create(100);
+ /* For comparison. */
+ default_policy = lttng_rate_policy_every_n_create(1);
+
+ LTTNG_ASSERT(policy && default_policy);
+
+ rotate_session_action = lttng_action_rotate_session_create();
+ ok(rotate_session_action, "Create rotate_session action");
+ ok(lttng_action_get_type(rotate_session_action) ==
+ LTTNG_ACTION_TYPE_ROTATE_SESSION,
+ "Action has type LTTNG_ACTION_TYPE_ROTATE_SESSION");
+
+ /* Session name setter. */
+ status = lttng_action_rotate_session_set_session_name(NULL, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,NULL) expect invalid");
+ status = lttng_action_rotate_session_set_session_name(
+ rotate_session_action, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (object,NULL) expect invalid");
+ status = lttng_action_rotate_session_set_session_name(
+ NULL, session_name);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,object) expect invalid");
+
+ /* Set the session name */
+ status = lttng_action_rotate_session_set_session_name(
+ rotate_session_action, session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
+
+ status = lttng_action_rotate_session_get_session_name(
+ rotate_session_action, &get_session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ !strcmp(session_name, get_session_name),
+ "Get session name, expected `%s` got `%s`",
+ session_name, get_session_name);
+
+ /* Validate the default policy for a rotate_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_rotate_session_get_rate_policy(
+ rotate_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ default_policy,
+ cur_policy),
+ "Default policy is every n=1");
+ }
+
+ /* Set a custom policy. */
+ status = lttng_action_rotate_session_set_rate_policy(
+ rotate_session_action, policy);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
+
+ /* Validate the custom policy for a rotate_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_rotate_session_get_rate_policy(
+ rotate_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ policy,
+ cur_policy),
+ "rotate_session action policy get");
+ }
+
+ /* Ser/des tests. */
+ ret = lttng_action_serialize(rotate_session_action, &payload);
+ ok(ret == 0, "Action rotate_session serialized");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ (void) lttng_action_create_from_payload(
+ &view, &rotate_session_action_from_buffer);
+ }
+ ok(rotate_session_action_from_buffer,
+ "rotate_session action created from payload is non-null");
+
+ ok(lttng_action_is_equal(rotate_session_action,
+ rotate_session_action_from_buffer),
+ "Serialized and de-serialized rotate_session action are equal");
+
+ lttng_rate_policy_destroy(default_policy);
+ lttng_rate_policy_destroy(policy);
+ lttng_action_destroy(rotate_session_action);
+ lttng_action_destroy(rotate_session_action_from_buffer);
+ lttng_payload_reset(&payload);
+}
+
+static void test_action_start_session(void)
+{
+ int ret;
+ enum lttng_action_status status;
+ struct lttng_action *start_session_action = NULL,
+ *start_session_action_from_buffer = NULL;
+ struct lttng_rate_policy *policy = NULL, *default_policy;
+ struct lttng_payload payload;
+ const char *session_name = "my_session_name";
+ const char *get_session_name;
+
+ lttng_payload_init(&payload);
+
+ /* To set. */
+ policy = lttng_rate_policy_every_n_create(100);
+ /* For comparison. */
+ default_policy = lttng_rate_policy_every_n_create(1);
+
+ LTTNG_ASSERT(policy && default_policy);
+
+ start_session_action = lttng_action_start_session_create();
+ ok(start_session_action, "Create start_session action");
+ ok(lttng_action_get_type(start_session_action) ==
+ LTTNG_ACTION_TYPE_START_SESSION,
+ "Action has type LTTNG_ACTION_TYPE_START_SESSION");
+
+ /* Session name setter. */
+ status = lttng_action_start_session_set_session_name(NULL, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,NULL) expect invalid");
+ status = lttng_action_start_session_set_session_name(
+ start_session_action, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (object,NULL) expect invalid");
+ status = lttng_action_start_session_set_session_name(
+ NULL, session_name);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,object) expect invalid");
+
+ /* Set the session name */
+ status = lttng_action_start_session_set_session_name(
+ start_session_action, session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
+
+ status = lttng_action_start_session_get_session_name(
+ start_session_action, &get_session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ !strcmp(session_name, get_session_name),
+ "Get session name, expected `%s` got `%s`",
+ session_name, get_session_name);
+
+ /* Validate the default policy for a start_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_start_session_get_rate_policy(
+ start_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ default_policy,
+ cur_policy),
+ "Default policy is every n=1");
+ }
+
+ /* Set a custom policy. */
+ status = lttng_action_start_session_set_rate_policy(
+ start_session_action, policy);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
+
+ /* Validate the custom policy for a start_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_start_session_get_rate_policy(
+ start_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ policy,
+ cur_policy),
+ "start_session action policy get");
+ }
+
+ /* Ser/des tests. */
+ ret = lttng_action_serialize(start_session_action, &payload);
+ ok(ret == 0, "Action start_session serialized");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ (void) lttng_action_create_from_payload(
+ &view, &start_session_action_from_buffer);
+ }
+ ok(start_session_action_from_buffer,
+ "start_session action created from payload is non-null");
+
+ ok(lttng_action_is_equal(start_session_action,
+ start_session_action_from_buffer),
+ "Serialized and de-serialized start_session action are equal");
+
+ lttng_rate_policy_destroy(default_policy);
+ lttng_rate_policy_destroy(policy);
+ lttng_action_destroy(start_session_action);
+ lttng_action_destroy(start_session_action_from_buffer);
+ lttng_payload_reset(&payload);
+}
+
+static void test_action_stop_session(void)
+{
+ int ret;
+ enum lttng_action_status status;
+ struct lttng_action *stop_session_action = NULL,
+ *stop_session_action_from_buffer = NULL;
+ struct lttng_rate_policy *policy = NULL, *default_policy;
+ struct lttng_payload payload;
+ const char *session_name = "my_session_name";
+ const char *get_session_name;
+
+ lttng_payload_init(&payload);
+
+ /* To set. */
+ policy = lttng_rate_policy_every_n_create(100);
+ /* For comparison. */
+ default_policy = lttng_rate_policy_every_n_create(1);
+
+ LTTNG_ASSERT(policy && default_policy);
+
+ stop_session_action = lttng_action_stop_session_create();
+ ok(stop_session_action, "Create stop_session action");
+ ok(lttng_action_get_type(stop_session_action) ==
+ LTTNG_ACTION_TYPE_STOP_SESSION,
+ "Action has type LTTNG_ACTION_TYPE_STOP_SESSION");
+
+ /* Session name setter. */
+ status = lttng_action_stop_session_set_session_name(NULL, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,NULL) expect invalid");
+ status = lttng_action_stop_session_set_session_name(
+ stop_session_action, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (object,NULL) expect invalid");
+ status = lttng_action_stop_session_set_session_name(NULL, session_name);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,object) expect invalid");
+
+ /* Set the session name */
+ status = lttng_action_stop_session_set_session_name(
+ stop_session_action, session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
+
+ status = lttng_action_stop_session_get_session_name(
+ stop_session_action, &get_session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ !strcmp(session_name, get_session_name),
+ "Get session name, expected `%s` got `%s`",
+ session_name, get_session_name);
+
+ /* Validate the default policy for a stop_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_stop_session_get_rate_policy(
+ stop_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ default_policy,
+ cur_policy),
+ "Default policy is every n=1");
+ }
+
+ /* Set a custom policy. */
+ status = lttng_action_stop_session_set_rate_policy(
+ stop_session_action, policy);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
+
+ /* Validate the custom policy for a stop_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_stop_session_get_rate_policy(
+ stop_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ policy,
+ cur_policy),
+ "stop_session action policy get");
+ }
+
+ /* Ser/des tests. */
+ ret = lttng_action_serialize(stop_session_action, &payload);
+ ok(ret == 0, "Action stop_session serialized");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ (void) lttng_action_create_from_payload(
+ &view, &stop_session_action_from_buffer);
+ }
+ ok(stop_session_action_from_buffer,
+ "stop_session action created from payload is non-null");
+
+ ok(lttng_action_is_equal(stop_session_action,
+ stop_session_action_from_buffer),
+ "Serialized and de-serialized stop_session action are equal");
+
+ lttng_rate_policy_destroy(default_policy);
+ lttng_rate_policy_destroy(policy);
+ lttng_action_destroy(stop_session_action);
+ lttng_action_destroy(stop_session_action_from_buffer);
+ lttng_payload_reset(&payload);
+}
+
+static void test_action_snapshot_session(void)
+{
+ int ret;
+ enum lttng_action_status status;
+ struct lttng_action *snapshot_session_action = NULL,
+ *snapshot_session_action_from_buffer = NULL;
+ struct lttng_rate_policy *policy = NULL, *default_policy;
+ struct lttng_payload payload;
+ const char *session_name = "my_session_name";
+ const char *get_session_name;
+
+ lttng_payload_init(&payload);
+
+ /* To set. */
+ policy = lttng_rate_policy_every_n_create(100);
+ /* For comparison. */
+ default_policy = lttng_rate_policy_every_n_create(1);
+
+ LTTNG_ASSERT(policy && default_policy);
+
+ snapshot_session_action = lttng_action_snapshot_session_create();
+ ok(snapshot_session_action, "Create snapshot_session action");
+ ok(lttng_action_get_type(snapshot_session_action) ==
+ LTTNG_ACTION_TYPE_SNAPSHOT_SESSION,
+ "Action has type LTTNG_ACTION_TYPE_SNAPSHOT_SESSION");
+
+ /* Session name setter. */
+ status = lttng_action_snapshot_session_set_session_name(NULL, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,NULL) expect invalid");
+ status = lttng_action_snapshot_session_set_session_name(
+ snapshot_session_action, NULL);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (object,NULL) expect invalid");
+ status = lttng_action_snapshot_session_set_session_name(
+ NULL, session_name);
+ ok(status == LTTNG_ACTION_STATUS_INVALID,
+ "Set session name (NULL,object) expect invalid");
+
+ /* Set the session name */
+ status = lttng_action_snapshot_session_set_session_name(
+ snapshot_session_action, session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set session name");
+
+ status = lttng_action_snapshot_session_get_session_name(
+ snapshot_session_action, &get_session_name);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ !strcmp(session_name, get_session_name),
+ "Get session name, expected `%s` got `%s`",
+ session_name, get_session_name);
+
+ /* Validate the default policy for a snapshot_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_snapshot_session_get_rate_policy(
+ snapshot_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ default_policy,
+ cur_policy),
+ "Default policy is every n=1");
+ }
+
+ /* Set a custom policy. */
+ status = lttng_action_snapshot_session_set_rate_policy(
+ snapshot_session_action, policy);
+ ok(status == LTTNG_ACTION_STATUS_OK, "Set rate policy");
+
+ /* Validate the custom policy for a snapshot_session action. */
+ {
+ const struct lttng_rate_policy *cur_policy = NULL;
+ status = lttng_action_snapshot_session_get_rate_policy(
+ snapshot_session_action, &cur_policy);
+ ok(status == LTTNG_ACTION_STATUS_OK &&
+ lttng_rate_policy_is_equal(
+ policy,
+ cur_policy),
+ "snapshot_session action policy get");
+ }
+
+ /* Ser/des tests. */
+ ret = lttng_action_serialize(snapshot_session_action, &payload);
+ ok(ret == 0, "Action snapshot_session serialized");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ (void) lttng_action_create_from_payload(
+ &view, &snapshot_session_action_from_buffer);
+ }
+ ok(snapshot_session_action_from_buffer,
+ "snapshot_session action created from payload is non-null");
+
+ ok(lttng_action_is_equal(snapshot_session_action,
+ snapshot_session_action_from_buffer),
+ "Serialized and de-serialized snapshot_session action are equal");
+
+ lttng_rate_policy_destroy(default_policy);
+ lttng_rate_policy_destroy(policy);
+ lttng_action_destroy(snapshot_session_action);
+ lttng_action_destroy(snapshot_session_action_from_buffer);
+ lttng_payload_reset(&payload);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_action_notify();
+ test_action_rotate_session();
+ test_action_start_session();
+ test_action_stop_session();
+ test_action_snapshot_session();
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2020 EfficiOS, inc.
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-
-#include <common/buffer-view.h>
-#include <tap/tap.h>
-
-static const int TEST_COUNT = 5;
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-static void test_contains_string(void)
-{
- const char buf[] = {'A', 'l', 'l', 'o', '\0'};
- struct lttng_buffer_view view = lttng_buffer_view_init(buf, 0, 5);
- struct lttng_buffer_view view_minus_one =
- lttng_buffer_view_init(buf, 0, 4);
-
- ok1(!lttng_buffer_view_contains_string(&view, buf, 4));
- ok1(lttng_buffer_view_contains_string(&view, buf, 5));
- ok1(!lttng_buffer_view_contains_string(&view, buf, 6));
-
- ok1(!lttng_buffer_view_contains_string(&view_minus_one, buf, 4));
- ok1(!lttng_buffer_view_contains_string(&view_minus_one, buf, 5));
-}
-
-int main(void)
-{
- plan_tests(TEST_COUNT);
-
- test_contains_string();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2020 EfficiOS, inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+
+#include <common/buffer-view.h>
+#include <tap/tap.h>
+
+static const int TEST_COUNT = 5;
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+static void test_contains_string(void)
+{
+ const char buf[] = {'A', 'l', 'l', 'o', '\0'};
+ struct lttng_buffer_view view = lttng_buffer_view_init(buf, 0, 5);
+ struct lttng_buffer_view view_minus_one =
+ lttng_buffer_view_init(buf, 0, 4);
+
+ ok1(!lttng_buffer_view_contains_string(&view, buf, 4));
+ ok1(lttng_buffer_view_contains_string(&view, buf, 5));
+ ok1(!lttng_buffer_view_contains_string(&view, buf, 6));
+
+ ok1(!lttng_buffer_view_contains_string(&view_minus_one, buf, 4));
+ ok1(!lttng_buffer_view_contains_string(&view_minus_one, buf, 5));
+}
+
+int main(void)
+{
+ plan_tests(TEST_COUNT);
+
+ test_contains_string();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * test_condition.c
- *
- * Unit tests for the condition API.
- *
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <tap/tap.h>
-
-#include <lttng/event.h>
-#include <lttng/event-rule/user-tracepoint.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule-matches.h>
-#include <lttng/condition/event-rule-matches-internal.h>
-#include <lttng/domain.h>
-#include <lttng/log-level-rule.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-#define NUM_TESTS 13
-
-static
-void test_condition_event_rule(void)
-{
- int ret, i;
- struct lttng_event_rule *tracepoint = NULL;
- const struct lttng_event_rule *tracepoint_tmp = NULL;
- enum lttng_event_rule_status status;
- struct lttng_condition *condition = NULL;
- struct lttng_condition *condition_from_buffer = NULL;
- enum lttng_condition_status condition_status;
- const char *pattern="my_event_*";
- const char *filter="msg_id == 23 && size >= 2048";
- const char *exclusions[] = { "my_event_test1", "my_event_test2", "my_event_test3" };
- struct lttng_log_level_rule *log_level_rule_at_least_as_severe = NULL;
- struct lttng_payload buffer;
-
- lttng_payload_init(&buffer);
-
- /* Create log level rule. */
- log_level_rule_at_least_as_severe =
- lttng_log_level_rule_at_least_as_severe_as_create(
- LTTNG_LOGLEVEL_WARNING);
- LTTNG_ASSERT(log_level_rule_at_least_as_severe);
-
- tracepoint = lttng_event_rule_user_tracepoint_create();
- ok(tracepoint, "user tracepoint");
-
- status = lttng_event_rule_user_tracepoint_set_name_pattern(tracepoint, pattern);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting pattern");
-
- status = lttng_event_rule_user_tracepoint_set_filter(tracepoint, filter);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting filter");
-
- status = lttng_event_rule_user_tracepoint_set_log_level_rule(
- tracepoint, log_level_rule_at_least_as_severe);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting log level range");
-
- for (i = 0; i < 3; i++) {
- status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
- tracepoint, exclusions[i]);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "Setting exclusion pattern");
- }
-
- condition = lttng_condition_event_rule_matches_create(tracepoint);
- ok(condition, "Created condition");
-
- condition_status = lttng_condition_event_rule_matches_get_rule(
- condition, &tracepoint_tmp);
- ok(condition_status == LTTNG_CONDITION_STATUS_OK,
- "Getting event rule from event rule condition");
- ok(tracepoint == tracepoint_tmp, "lttng_condition_event_rule_get_rule provides a reference to the original rule");
-
- ret = lttng_condition_serialize(condition, &buffer);
- ok(ret == 0, "Condition serialized");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(&buffer, 0, -1);
-
- (void) lttng_condition_create_from_payload(
- &view, &condition_from_buffer);
- }
-
- ok(condition_from_buffer, "Condition created from payload is non-null");
-
- ok(lttng_condition_is_equal(condition, condition_from_buffer),
- "Serialized and de-serialized conditions are equal");
-
- lttng_payload_reset(&buffer);
- lttng_event_rule_destroy(tracepoint);
- lttng_condition_destroy(condition);
- lttng_condition_destroy(condition_from_buffer);
- lttng_log_level_rule_destroy(log_level_rule_at_least_as_severe);
-}
-
-int main(int argc, const char *argv[])
-{
- plan_tests(NUM_TESTS);
- test_condition_event_rule();
- return exit_status();
-}
--- /dev/null
+/*
+ * test_condition.c
+ *
+ * Unit tests for the condition API.
+ *
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <lttng/event.h>
+#include <lttng/event-rule/user-tracepoint.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/event-rule-matches.h>
+#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/domain.h>
+#include <lttng/log-level-rule.h>
+#include <common/dynamic-buffer.h>
+#include <common/buffer-view.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 13
+
+static
+void test_condition_event_rule(void)
+{
+ int ret, i;
+ struct lttng_event_rule *tracepoint = NULL;
+ const struct lttng_event_rule *tracepoint_tmp = NULL;
+ enum lttng_event_rule_status status;
+ struct lttng_condition *condition = NULL;
+ struct lttng_condition *condition_from_buffer = NULL;
+ enum lttng_condition_status condition_status;
+ const char *pattern="my_event_*";
+ const char *filter="msg_id == 23 && size >= 2048";
+ const char *exclusions[] = { "my_event_test1", "my_event_test2", "my_event_test3" };
+ struct lttng_log_level_rule *log_level_rule_at_least_as_severe = NULL;
+ struct lttng_payload buffer;
+
+ lttng_payload_init(&buffer);
+
+ /* Create log level rule. */
+ log_level_rule_at_least_as_severe =
+ lttng_log_level_rule_at_least_as_severe_as_create(
+ LTTNG_LOGLEVEL_WARNING);
+ LTTNG_ASSERT(log_level_rule_at_least_as_severe);
+
+ tracepoint = lttng_event_rule_user_tracepoint_create();
+ ok(tracepoint, "user tracepoint");
+
+ status = lttng_event_rule_user_tracepoint_set_name_pattern(tracepoint, pattern);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting pattern");
+
+ status = lttng_event_rule_user_tracepoint_set_filter(tracepoint, filter);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting filter");
+
+ status = lttng_event_rule_user_tracepoint_set_log_level_rule(
+ tracepoint, log_level_rule_at_least_as_severe);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting log level range");
+
+ for (i = 0; i < 3; i++) {
+ status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
+ tracepoint, exclusions[i]);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Setting exclusion pattern");
+ }
+
+ condition = lttng_condition_event_rule_matches_create(tracepoint);
+ ok(condition, "Created condition");
+
+ condition_status = lttng_condition_event_rule_matches_get_rule(
+ condition, &tracepoint_tmp);
+ ok(condition_status == LTTNG_CONDITION_STATUS_OK,
+ "Getting event rule from event rule condition");
+ ok(tracepoint == tracepoint_tmp, "lttng_condition_event_rule_get_rule provides a reference to the original rule");
+
+ ret = lttng_condition_serialize(condition, &buffer);
+ ok(ret == 0, "Condition serialized");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(&buffer, 0, -1);
+
+ (void) lttng_condition_create_from_payload(
+ &view, &condition_from_buffer);
+ }
+
+ ok(condition_from_buffer, "Condition created from payload is non-null");
+
+ ok(lttng_condition_is_equal(condition, condition_from_buffer),
+ "Serialized and de-serialized conditions are equal");
+
+ lttng_payload_reset(&buffer);
+ lttng_event_rule_destroy(tracepoint);
+ lttng_condition_destroy(condition);
+ lttng_condition_destroy(condition_from_buffer);
+ lttng_log_level_rule_destroy(log_level_rule_at_least_as_severe);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_condition_event_rule();
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <common/compat/directory-handle.h>
-#include <common/compat/errno.h>
-#include <common/error.h>
-#include <tap/tap.h>
-
-#define TEST_COUNT 9
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose = 3;
-int lttng_opt_mi;
-
-#define DIR_CREATION_MODE (S_IRWXU | S_IRWXG)
-
-/*
- * Returns the number of tests that ran (irrespective of the result) or a
- * negative value on error (will abort all tests).
- */
-typedef int(test_func)(const char *test_base_path);
-
-static test_func test_rmdir_fail_non_empty;
-static test_func test_rmdir_skip_non_empty;
-
-static test_func *const test_funcs[] = {
- &test_rmdir_fail_non_empty,
- &test_rmdir_skip_non_empty,
-};
-
-static bool dir_exists(const char *path)
-{
- int ret;
- struct stat st;
-
- ret = stat(path, &st);
- return ret == 0 && S_ISDIR(st.st_mode);
-}
-
-/*
- * Create a non-empty folder hierarchy from a directory handle:
- *
- * test_root_name
- * └── a
- * └── b
- * ├── c
- * │ └── d
- * └── e
- * ├── f
- * └── file1
- */
-static int create_non_empty_hierarchy_with_root(
- struct lttng_directory_handle *test_dir_handle,
- const char *test_root_name)
-{
- int ret;
- const int file_flags = O_WRONLY | O_CREAT | O_TRUNC;
- const mode_t file_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
- char *branch_name = NULL;
-
- ret = asprintf(&branch_name, "%s/%s", test_root_name, "a/b/c/d");
- if (ret < 0) {
- diag("Failed to format folder path");
- goto end;
- }
- ret = lttng_directory_handle_create_subdirectory_recursive(
- test_dir_handle,
- branch_name,
- DIR_CREATION_MODE);
- if (ret) {
- diag("Failed to create test folder hierarchy %s", branch_name);
- goto end;
- }
-
- free(branch_name);
- ret = asprintf(&branch_name, "%s/%s", test_root_name, "a/b/e/f");
- if (ret < 0) {
- diag("Failed to format folder path");
- goto end;
- }
- ret = lttng_directory_handle_create_subdirectory_recursive(
- test_dir_handle,
- branch_name,
- DIR_CREATION_MODE);
- if (ret) {
- diag("Failed to create test folder hierarchy %s", branch_name);
- goto end;
- }
-
- free(branch_name);
- ret = asprintf(&branch_name, "%s/%s", test_root_name, "a/b/e/file1");
- if (ret < 0) {
- diag("Failed to format file path");
- goto end;
- }
- ret = lttng_directory_handle_open_file(
- test_dir_handle, branch_name, file_flags, file_mode);
- if (ret < 0) {
- diag("Failed to create file %s", branch_name);
- goto end;
- }
- ret = close(ret);
- if (ret) {
- PERROR("Failed to close fd to newly created file %s",
- branch_name);
- goto end;
- }
-end:
- free(branch_name);
- return ret;
-}
-
-/* Remove "file1" from the test folder hierarchy. */
-static
-int remove_file_from_hierarchy(struct lttng_directory_handle *test_dir_handle,
- const char *test_root_name)
-{
- int ret;
- char *file_name = NULL;
-
- ret = asprintf(&file_name, "%s/%s", test_root_name, "a/b/e/file1");
- if (ret < 0) {
- diag("Failed to format file path");
- goto end;
- }
-
- ret = lttng_directory_handle_unlink_file(test_dir_handle,
- file_name);
- if (ret) {
- PERROR("Failed to unlink file %s", file_name);
- goto end;
- }
-end:
- free(file_name);
- return ret;
-}
-
-static int test_rmdir_fail_non_empty(const char *test_dir)
-{
- int ret, tests_ran = 0;
- struct lttng_directory_handle *test_dir_handle;
- char *created_dir = NULL;
- const char test_root_name[] = "fail_non_empty";
- char *test_dir_path = NULL;
-
- diag("rmdir (fail if non-empty)");
-
- test_dir_handle = lttng_directory_handle_create(test_dir);
- ok(test_dir_handle, "Initialized directory handle from the test directory");
- tests_ran++;
- if (!test_dir_handle) {
- ret = -1;
- goto end;
- }
-
- ret = create_non_empty_hierarchy_with_root(test_dir_handle, test_root_name);
- if (ret) {
- diag("Failed to setup folder/file hierarchy to run test");
- goto end;
- }
-
- ret = lttng_directory_handle_remove_subdirectory_recursive(
- test_dir_handle, test_root_name,
- LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG);
- ok(ret == -1, "Error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
- tests_ran++;
-
- ret = remove_file_from_hierarchy(test_dir_handle, test_root_name);
- if (ret) {
- diag("Failed to remove file from test folder hierarchy");
- goto end;
- }
-
- ret = lttng_directory_handle_remove_subdirectory_recursive(
- test_dir_handle, test_root_name,
- LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG);
- ok(ret == 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
- tests_ran++;
-
- ret = asprintf(&test_dir_path, "%s/%s", test_dir, test_root_name);
- if (ret < 0) {
- diag("Failed to format test directory path");
- goto end;
- }
- ok(!dir_exists(test_dir_path) && errno == ENOENT,
- "Folder hierarchy %s successfully removed",
- test_dir_path);
- tests_ran++;
- ret = 0;
-end:
- lttng_directory_handle_put(test_dir_handle);
- free(created_dir);
- free(test_dir_path);
- return ret == 0 ? tests_ran : ret;
-}
-
-static int test_rmdir_skip_non_empty(const char *test_dir)
-{
- int ret, tests_ran = 0;
- struct lttng_directory_handle *test_dir_handle;
- char *created_dir = NULL;
- const char test_root_name[] = "skip_non_empty";
- char *test_dir_path = NULL;
-
- diag("rmdir (skip if non-empty)");
-
- test_dir_handle = lttng_directory_handle_create(test_dir);
- ok(test_dir_handle, "Initialized directory handle from the test directory");
- tests_ran++;
- if (!test_dir_handle) {
- ret = -1;
- goto end;
- }
-
- ret = create_non_empty_hierarchy_with_root(test_dir_handle, test_root_name);
- if (ret) {
- diag("Failed to setup folder/file hierarchy to run test");
- goto end;
- }
-
- ret = lttng_directory_handle_remove_subdirectory_recursive(
- test_dir_handle, test_root_name,
- LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
- ok(ret == 0, "No error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
- tests_ran++;
-
- ret = asprintf(&test_dir_path, "%s/%s", test_dir, test_root_name);
- if (ret < 0) {
- diag("Failed to format test directory path");
- goto end;
- }
- ok(dir_exists(test_dir_path), "Test directory still exists after skip");
- tests_ran++;
-
- ret = remove_file_from_hierarchy(test_dir_handle, test_root_name);
- if (ret) {
- diag("Failed to remove file from test folder hierarchy");
- goto end;
- }
-
- ret = lttng_directory_handle_remove_subdirectory_recursive(
- test_dir_handle, test_root_name,
- LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
- ok(ret == 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
- tests_ran++;
-
- ok(!dir_exists(test_dir_path) && errno == ENOENT,
- "Folder hierarchy %s successfully removed",
- test_dir_path);
- tests_ran++;
- ret = 0;
-end:
- lttng_directory_handle_put(test_dir_handle);
- free(created_dir);
- free(test_dir_path);
- return ret == 0 ? tests_ran : ret;
-}
-
-int main(int argc, char **argv)
-{
- int ret;
- char test_dir[] = "/tmp/lttng-XXXXXX";
- int tests_left = TEST_COUNT;
- size_t func_idx;
-
- plan_tests(TEST_COUNT);
-
- diag("lttng_directory_handle tests");
-
- if (!mkdtemp(test_dir)) {
- diag("Failed to generate temporary test directory");
- goto end;
- }
-
- for (func_idx = 0; func_idx < sizeof(test_funcs) / sizeof(*test_funcs);
- func_idx++) {
- tests_left -= test_funcs[func_idx](test_dir);
- }
- if (tests_left) {
- diag("Skipping %d tests that could not be executed due to a prior error",
- tests_left);
- skip(tests_left, "test due to an error");
- }
-end:
- ret = rmdir(test_dir);
- if (ret) {
- diag("Failed to clean-up test directory: %s", strerror(errno));
- }
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <common/compat/directory-handle.h>
+#include <common/compat/errno.h>
+#include <common/error.h>
+#include <tap/tap.h>
+
+#define TEST_COUNT 9
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose = 3;
+int lttng_opt_mi;
+
+#define DIR_CREATION_MODE (S_IRWXU | S_IRWXG)
+
+/*
+ * Returns the number of tests that ran (irrespective of the result) or a
+ * negative value on error (will abort all tests).
+ */
+typedef int(test_func)(const char *test_base_path);
+
+static test_func test_rmdir_fail_non_empty;
+static test_func test_rmdir_skip_non_empty;
+
+static test_func *const test_funcs[] = {
+ &test_rmdir_fail_non_empty,
+ &test_rmdir_skip_non_empty,
+};
+
+static bool dir_exists(const char *path)
+{
+ int ret;
+ struct stat st;
+
+ ret = stat(path, &st);
+ return ret == 0 && S_ISDIR(st.st_mode);
+}
+
+/*
+ * Create a non-empty folder hierarchy from a directory handle:
+ *
+ * test_root_name
+ * └── a
+ * └── b
+ * ├── c
+ * │ └── d
+ * └── e
+ * ├── f
+ * └── file1
+ */
+static int create_non_empty_hierarchy_with_root(
+ struct lttng_directory_handle *test_dir_handle,
+ const char *test_root_name)
+{
+ int ret;
+ const int file_flags = O_WRONLY | O_CREAT | O_TRUNC;
+ const mode_t file_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+ char *branch_name = NULL;
+
+ ret = asprintf(&branch_name, "%s/%s", test_root_name, "a/b/c/d");
+ if (ret < 0) {
+ diag("Failed to format folder path");
+ goto end;
+ }
+ ret = lttng_directory_handle_create_subdirectory_recursive(
+ test_dir_handle,
+ branch_name,
+ DIR_CREATION_MODE);
+ if (ret) {
+ diag("Failed to create test folder hierarchy %s", branch_name);
+ goto end;
+ }
+
+ free(branch_name);
+ ret = asprintf(&branch_name, "%s/%s", test_root_name, "a/b/e/f");
+ if (ret < 0) {
+ diag("Failed to format folder path");
+ goto end;
+ }
+ ret = lttng_directory_handle_create_subdirectory_recursive(
+ test_dir_handle,
+ branch_name,
+ DIR_CREATION_MODE);
+ if (ret) {
+ diag("Failed to create test folder hierarchy %s", branch_name);
+ goto end;
+ }
+
+ free(branch_name);
+ ret = asprintf(&branch_name, "%s/%s", test_root_name, "a/b/e/file1");
+ if (ret < 0) {
+ diag("Failed to format file path");
+ goto end;
+ }
+ ret = lttng_directory_handle_open_file(
+ test_dir_handle, branch_name, file_flags, file_mode);
+ if (ret < 0) {
+ diag("Failed to create file %s", branch_name);
+ goto end;
+ }
+ ret = close(ret);
+ if (ret) {
+ PERROR("Failed to close fd to newly created file %s",
+ branch_name);
+ goto end;
+ }
+end:
+ free(branch_name);
+ return ret;
+}
+
+/* Remove "file1" from the test folder hierarchy. */
+static
+int remove_file_from_hierarchy(struct lttng_directory_handle *test_dir_handle,
+ const char *test_root_name)
+{
+ int ret;
+ char *file_name = NULL;
+
+ ret = asprintf(&file_name, "%s/%s", test_root_name, "a/b/e/file1");
+ if (ret < 0) {
+ diag("Failed to format file path");
+ goto end;
+ }
+
+ ret = lttng_directory_handle_unlink_file(test_dir_handle,
+ file_name);
+ if (ret) {
+ PERROR("Failed to unlink file %s", file_name);
+ goto end;
+ }
+end:
+ free(file_name);
+ return ret;
+}
+
+static int test_rmdir_fail_non_empty(const char *test_dir)
+{
+ int ret, tests_ran = 0;
+ struct lttng_directory_handle *test_dir_handle;
+ char *created_dir = NULL;
+ const char test_root_name[] = "fail_non_empty";
+ char *test_dir_path = NULL;
+
+ diag("rmdir (fail if non-empty)");
+
+ test_dir_handle = lttng_directory_handle_create(test_dir);
+ ok(test_dir_handle, "Initialized directory handle from the test directory");
+ tests_ran++;
+ if (!test_dir_handle) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = create_non_empty_hierarchy_with_root(test_dir_handle, test_root_name);
+ if (ret) {
+ diag("Failed to setup folder/file hierarchy to run test");
+ goto end;
+ }
+
+ ret = lttng_directory_handle_remove_subdirectory_recursive(
+ test_dir_handle, test_root_name,
+ LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG);
+ ok(ret == -1, "Error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
+ tests_ran++;
+
+ ret = remove_file_from_hierarchy(test_dir_handle, test_root_name);
+ if (ret) {
+ diag("Failed to remove file from test folder hierarchy");
+ goto end;
+ }
+
+ ret = lttng_directory_handle_remove_subdirectory_recursive(
+ test_dir_handle, test_root_name,
+ LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG);
+ ok(ret == 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
+ tests_ran++;
+
+ ret = asprintf(&test_dir_path, "%s/%s", test_dir, test_root_name);
+ if (ret < 0) {
+ diag("Failed to format test directory path");
+ goto end;
+ }
+ ok(!dir_exists(test_dir_path) && errno == ENOENT,
+ "Folder hierarchy %s successfully removed",
+ test_dir_path);
+ tests_ran++;
+ ret = 0;
+end:
+ lttng_directory_handle_put(test_dir_handle);
+ free(created_dir);
+ free(test_dir_path);
+ return ret == 0 ? tests_ran : ret;
+}
+
+static int test_rmdir_skip_non_empty(const char *test_dir)
+{
+ int ret, tests_ran = 0;
+ struct lttng_directory_handle *test_dir_handle;
+ char *created_dir = NULL;
+ const char test_root_name[] = "skip_non_empty";
+ char *test_dir_path = NULL;
+
+ diag("rmdir (skip if non-empty)");
+
+ test_dir_handle = lttng_directory_handle_create(test_dir);
+ ok(test_dir_handle, "Initialized directory handle from the test directory");
+ tests_ran++;
+ if (!test_dir_handle) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = create_non_empty_hierarchy_with_root(test_dir_handle, test_root_name);
+ if (ret) {
+ diag("Failed to setup folder/file hierarchy to run test");
+ goto end;
+ }
+
+ ret = lttng_directory_handle_remove_subdirectory_recursive(
+ test_dir_handle, test_root_name,
+ LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
+ ok(ret == 0, "No error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
+ tests_ran++;
+
+ ret = asprintf(&test_dir_path, "%s/%s", test_dir, test_root_name);
+ if (ret < 0) {
+ diag("Failed to format test directory path");
+ goto end;
+ }
+ ok(dir_exists(test_dir_path), "Test directory still exists after skip");
+ tests_ran++;
+
+ ret = remove_file_from_hierarchy(test_dir_handle, test_root_name);
+ if (ret) {
+ diag("Failed to remove file from test folder hierarchy");
+ goto end;
+ }
+
+ ret = lttng_directory_handle_remove_subdirectory_recursive(
+ test_dir_handle, test_root_name,
+ LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
+ ok(ret == 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
+ tests_ran++;
+
+ ok(!dir_exists(test_dir_path) && errno == ENOENT,
+ "Folder hierarchy %s successfully removed",
+ test_dir_path);
+ tests_ran++;
+ ret = 0;
+end:
+ lttng_directory_handle_put(test_dir_handle);
+ free(created_dir);
+ free(test_dir_path);
+ return ret == 0 ? tests_ran : ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ char test_dir[] = "/tmp/lttng-XXXXXX";
+ int tests_left = TEST_COUNT;
+ size_t func_idx;
+
+ plan_tests(TEST_COUNT);
+
+ diag("lttng_directory_handle tests");
+
+ if (!mkdtemp(test_dir)) {
+ diag("Failed to generate temporary test directory");
+ goto end;
+ }
+
+ for (func_idx = 0; func_idx < sizeof(test_funcs) / sizeof(*test_funcs);
+ func_idx++) {
+ tests_left -= test_funcs[func_idx](test_dir);
+ }
+ if (tests_left) {
+ diag("Skipping %d tests that could not be executed due to a prior error",
+ tests_left);
+ skip(tests_left, "test due to an error");
+ }
+end:
+ ret = rmdir(test_dir);
+ if (ret) {
+ diag("Failed to clean-up test directory: %s", strerror(errno));
+ }
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright 2020 EfficiOS, Inc.
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <common/bytecode/bytecode.h>
-#include <lttng/event-expr-internal.h>
-#include <lttng/event-expr.h>
-#include <tap/tap.h>
-
-#define NR_TESTS 4
-
-static
-void test_event_payload_field(void)
-{
- struct lttng_event_expr *event_expr;
- struct lttng_bytecode *bytecode = NULL;
- int ret;
-
- event_expr = lttng_event_expr_event_payload_field_create("tourlou");
- ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
-
- ok(ret == 0, "event payload field");
-
- lttng_event_expr_destroy(event_expr);
- free(bytecode);
-}
-
-static
-void test_channel_context_field(void)
-{
- struct lttng_event_expr *event_expr;
- struct lttng_bytecode *bytecode = NULL;
- int ret;
-
- event_expr = lttng_event_expr_channel_context_field_create("tourlou");
- ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
-
- ok(ret == 0, "channel context field");
-
- lttng_event_expr_destroy(event_expr);
- free(bytecode);
-}
-
-static
-void test_app_specific_context_field(void)
-{
- struct lttng_event_expr *event_expr;
- struct lttng_bytecode *bytecode = NULL;
- int ret;
-
- event_expr = lttng_event_expr_app_specific_context_field_create("Bob", "Leponge");
- ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
-
- ok(ret == 0, "app-specific context field");
-
- lttng_event_expr_destroy(event_expr);
- free(bytecode);
-}
-
-static
-void test_array_field_element(void)
-{
- struct lttng_event_expr *event_expr;
- struct lttng_bytecode *bytecode = NULL;
- int ret;
-
- event_expr = lttng_event_expr_event_payload_field_create("allo");
- event_expr = lttng_event_expr_array_field_element_create(event_expr, 168);
- ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
-
- ok(ret == 0, "array field element");
-
- lttng_event_expr_destroy(event_expr);
- free(bytecode);
-}
-
-int main(void)
-{
- plan_tests(NR_TESTS);
-
- test_event_payload_field();
- test_channel_context_field();
- test_app_specific_context_field();
- test_array_field_element();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright 2020 EfficiOS, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <common/bytecode/bytecode.h>
+#include <lttng/event-expr-internal.h>
+#include <lttng/event-expr.h>
+#include <tap/tap.h>
+
+#define NR_TESTS 4
+
+static
+void test_event_payload_field(void)
+{
+ struct lttng_event_expr *event_expr;
+ struct lttng_bytecode *bytecode = NULL;
+ int ret;
+
+ event_expr = lttng_event_expr_event_payload_field_create("tourlou");
+ ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
+
+ ok(ret == 0, "event payload field");
+
+ lttng_event_expr_destroy(event_expr);
+ free(bytecode);
+}
+
+static
+void test_channel_context_field(void)
+{
+ struct lttng_event_expr *event_expr;
+ struct lttng_bytecode *bytecode = NULL;
+ int ret;
+
+ event_expr = lttng_event_expr_channel_context_field_create("tourlou");
+ ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
+
+ ok(ret == 0, "channel context field");
+
+ lttng_event_expr_destroy(event_expr);
+ free(bytecode);
+}
+
+static
+void test_app_specific_context_field(void)
+{
+ struct lttng_event_expr *event_expr;
+ struct lttng_bytecode *bytecode = NULL;
+ int ret;
+
+ event_expr = lttng_event_expr_app_specific_context_field_create("Bob", "Leponge");
+ ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
+
+ ok(ret == 0, "app-specific context field");
+
+ lttng_event_expr_destroy(event_expr);
+ free(bytecode);
+}
+
+static
+void test_array_field_element(void)
+{
+ struct lttng_event_expr *event_expr;
+ struct lttng_bytecode *bytecode = NULL;
+ int ret;
+
+ event_expr = lttng_event_expr_event_payload_field_create("allo");
+ event_expr = lttng_event_expr_array_field_element_create(event_expr, 168);
+ ret = lttng_event_expr_to_bytecode(event_expr, &bytecode);
+
+ ok(ret == 0, "array field element");
+
+ lttng_event_expr_destroy(event_expr);
+ free(bytecode);
+}
+
+int main(void)
+{
+ plan_tests(NR_TESTS);
+
+ test_event_payload_field();
+ test_channel_context_field();
+ test_app_specific_context_field();
+ test_array_field_element();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * Unit tests for the notification API.
- *
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <tap/tap.h>
-
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/domain.h>
-#include <lttng/event-rule/jul-logging-internal.h>
-#include <lttng/event-rule/jul-logging.h>
-#include <lttng/event-rule/kernel-kprobe-internal.h>
-#include <lttng/event-rule/kernel-kprobe.h>
-#include <lttng/event-rule/kernel-syscall-internal.h>
-#include <lttng/event-rule/kernel-syscall.h>
-#include <lttng/event-rule/python-logging-internal.h>
-#include <lttng/event-rule/python-logging.h>
-#include <lttng/event-rule/kernel-tracepoint-internal.h>
-#include <lttng/event-rule/kernel-tracepoint.h>
-#include <lttng/event-rule/kernel-uprobe-internal.h>
-#include <lttng/event-rule/kernel-uprobe.h>
-#include <lttng/event-rule/user-tracepoint-internal.h>
-#include <lttng/event-rule/user-tracepoint.h>
-#include <lttng/event.h>
-#include <lttng/kernel-probe-internal.h>
-#include <lttng/kernel-probe.h>
-#include <lttng/userspace-probe-internal.h>
-#include <lttng/userspace-probe.h>
-#include "bin/lttng/loglevel.h"
-
-/* For error.h. */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-#define NUM_TESTS 212
-
-struct tracepoint_test {
- enum lttng_domain_type type;
- bool support_name_pattern_exclusion;
-};
-
-typedef const char *(*log_level_name_getter)(int log_level);
-
-typedef struct lttng_event_rule *(*event_rule_create)(void);
-typedef enum lttng_event_rule_status (*event_rule_set_log_level)(
- struct lttng_event_rule *rule,
- const struct lttng_log_level_rule *log_level_rule);
-
-static
-void test_event_rule_kernel_tracepoint(void)
-{
- struct lttng_event_rule *tracepoint = NULL;
- struct lttng_event_rule *tracepoint_from_buffer = NULL;
- enum lttng_event_rule_status status;
- const char *pattern="my_event_*";
- const char *filter="msg_id == 23 && size >= 2048";
- const char *tmp;
- struct lttng_payload payload;
-
- diag("Testing lttng_event_rule_kernel_tracepoint.");
-
- lttng_payload_init(&payload);
-
- tracepoint = lttng_event_rule_kernel_tracepoint_create();
- ok(tracepoint, "tracepoint object.");
-
- status = lttng_event_rule_kernel_tracepoint_set_name_pattern(tracepoint, pattern);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
- status = lttng_event_rule_kernel_tracepoint_get_name_pattern(tracepoint, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
- ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
-
- status = lttng_event_rule_kernel_tracepoint_set_filter(tracepoint, filter);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
- status = lttng_event_rule_kernel_tracepoint_get_filter(tracepoint, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
- ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
-
- ok(lttng_event_rule_serialize(tracepoint, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &tracepoint_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(tracepoint, tracepoint_from_buffer), "serialized and from buffer are equal.");
-
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(tracepoint);
- lttng_event_rule_destroy(tracepoint_from_buffer);
-}
-
-static
-void test_event_rule_user_tracepoint(void)
-{
- int i;
- unsigned int count;
- struct lttng_event_rule *tracepoint = NULL;
- struct lttng_event_rule *tracepoint_from_buffer = NULL;
- enum lttng_event_rule_status status;
- const char *pattern="my_event_*";
- const char *filter="msg_id == 23 && size >= 2048";
- const char *tmp;
- const char *name_pattern_exclusions[] = {"my_event_test1", "my_event_test2" ,"my_event_test3"};
- struct lttng_log_level_rule *log_level_rule = NULL;
- const struct lttng_log_level_rule *log_level_rule_return = NULL;
- struct lttng_payload payload;
-
- diag("Testing lttng_event_rule_user_tracepoint.");
-
- lttng_payload_init(&payload);
-
- log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
- LTTNG_ASSERT(log_level_rule);
-
- tracepoint = lttng_event_rule_user_tracepoint_create();
- ok(tracepoint, "user tracepoint object.");
-
- status = lttng_event_rule_user_tracepoint_set_name_pattern(tracepoint, pattern);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
- status = lttng_event_rule_user_tracepoint_get_name_pattern(tracepoint, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
- ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
-
- status = lttng_event_rule_user_tracepoint_set_filter(tracepoint, filter);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
- status = lttng_event_rule_user_tracepoint_get_filter(tracepoint, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
- ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
-
- status = lttng_event_rule_user_tracepoint_get_log_level_rule(tracepoint, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
-
- status = lttng_event_rule_user_tracepoint_set_log_level_rule(
- tracepoint, log_level_rule);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
- status = lttng_event_rule_user_tracepoint_get_log_level_rule(
- tracepoint, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
-
- /* Name pattern exclusions */
- for (i = 0; i < 3; i++) {
- status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
- tracepoint, name_pattern_exclusions[i]);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "setting name pattern exclusions \"%s\"",
- name_pattern_exclusions[i]);
- }
-
- status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
- tracepoint, &count);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "getting name pattern exclusion count.");
- ok(count == 3, "count is %d/3", count);
-
- for (i = 0; i < count; i++) {
- status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
- tracepoint, i, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "getting name pattern exclusion at index %d.",
- i);
- ok(!strncmp(name_pattern_exclusions[i], tmp,
- strlen(name_pattern_exclusions[i])),
- "%s == %s.", tmp, name_pattern_exclusions[i]);
- }
-
- ok(lttng_event_rule_serialize(tracepoint, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &tracepoint_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(tracepoint, tracepoint_from_buffer), "serialized and from buffer are equal.");
-
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(tracepoint);
- lttng_event_rule_destroy(tracepoint_from_buffer);
- lttng_log_level_rule_destroy(log_level_rule);
-}
-
-static void test_event_rule_syscall(void)
-{
- struct lttng_event_rule *syscall = NULL;
- struct lttng_event_rule *syscall_from_buffer = NULL;
- enum lttng_event_rule_status status;
- const char *pattern = "my_event_*";
- const char *filter = "msg_id == 23 && size >= 2048";
- const char *tmp;
- struct lttng_payload payload;
-
- diag("Event rule syscall.");
-
- lttng_payload_init(&payload);
-
- syscall = lttng_event_rule_kernel_syscall_create(LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY);
- ok(syscall, "syscall object.");
-
- status = lttng_event_rule_kernel_syscall_set_name_pattern(syscall, pattern);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
- status = lttng_event_rule_kernel_syscall_get_name_pattern(syscall, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
- ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
-
- status = lttng_event_rule_kernel_syscall_set_filter(syscall, filter);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
- status = lttng_event_rule_kernel_syscall_get_filter(syscall, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
- ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
-
- ok(lttng_event_rule_serialize(syscall, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &syscall_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(syscall, syscall_from_buffer),
- "serialized and from buffer are equal.");
-
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(syscall);
- lttng_event_rule_destroy(syscall_from_buffer);
-}
-
-static
-void test_event_rule_jul_logging(void)
-{
- struct lttng_event_rule *jul_logging = NULL;
- struct lttng_event_rule *jul_logging_from_buffer = NULL;
- enum lttng_event_rule_status status;
- const char *pattern="my_event_*";
- const char *filter="msg_id == 23 && size >= 2048";
- const char *tmp;
- struct lttng_log_level_rule *log_level_rule = NULL;
- const struct lttng_log_level_rule *log_level_rule_return = NULL;
- struct lttng_payload payload;
-
- diag("Testing lttng_event_rule_user_jul_logging.");
-
- lttng_payload_init(&payload);
-
- log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
- LTTNG_ASSERT(log_level_rule);
-
- jul_logging = lttng_event_rule_jul_logging_create();
- ok(jul_logging, "jul_logging object.");
-
- status = lttng_event_rule_jul_logging_set_name_pattern(jul_logging, pattern);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
- status = lttng_event_rule_jul_logging_get_name_pattern(jul_logging, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
- ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
-
- status = lttng_event_rule_jul_logging_set_filter(jul_logging, filter);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
- status = lttng_event_rule_jul_logging_get_filter(jul_logging, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
- ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
-
- status = lttng_event_rule_jul_logging_get_log_level_rule(jul_logging, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
-
- status = lttng_event_rule_jul_logging_set_log_level_rule(
- jul_logging, log_level_rule);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
- status = lttng_event_rule_jul_logging_get_log_level_rule(
- jul_logging, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
-
- ok(lttng_event_rule_serialize(jul_logging, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &jul_logging_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(jul_logging, jul_logging_from_buffer), "serialized and from buffer are equal.");
-
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(jul_logging);
- lttng_event_rule_destroy(jul_logging_from_buffer);
- lttng_log_level_rule_destroy(log_level_rule);
-}
-
-static
-void test_event_rule_log4j_logging(void)
-{
- struct lttng_event_rule *log4j_logging = NULL;
- struct lttng_event_rule *log4j_logging_from_buffer = NULL;
- enum lttng_event_rule_status status;
- const char *pattern="my_event_*";
- const char *filter="msg_id == 23 && size >= 2048";
- const char *tmp;
- struct lttng_log_level_rule *log_level_rule = NULL;
- const struct lttng_log_level_rule *log_level_rule_return = NULL;
- struct lttng_payload payload;
-
- diag("Testing lttng_event_rule_user_log4j_logging.");
-
- lttng_payload_init(&payload);
-
- log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
- LTTNG_ASSERT(log_level_rule);
-
- log4j_logging = lttng_event_rule_log4j_logging_create();
- ok(log4j_logging, "log4j_logging object.");
-
- status = lttng_event_rule_log4j_logging_set_name_pattern(log4j_logging, pattern);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
- status = lttng_event_rule_log4j_logging_get_name_pattern(log4j_logging, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
- ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
-
- status = lttng_event_rule_log4j_logging_set_filter(log4j_logging, filter);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
- status = lttng_event_rule_log4j_logging_get_filter(log4j_logging, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
- ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
-
- status = lttng_event_rule_log4j_logging_get_log_level_rule(log4j_logging, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
-
- status = lttng_event_rule_log4j_logging_set_log_level_rule(
- log4j_logging, log_level_rule);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
- status = lttng_event_rule_log4j_logging_get_log_level_rule(
- log4j_logging, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
-
- ok(lttng_event_rule_serialize(log4j_logging, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &log4j_logging_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(log4j_logging, log4j_logging_from_buffer), "serialized and from buffer are equal.");
-
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(log4j_logging);
- lttng_event_rule_destroy(log4j_logging_from_buffer);
- lttng_log_level_rule_destroy(log_level_rule);
-}
-
-static
-void test_event_rule_python_logging(void)
-{
- struct lttng_event_rule *python_logging = NULL;
- struct lttng_event_rule *python_logging_from_buffer = NULL;
- enum lttng_event_rule_status status;
- const char *pattern="my_event_*";
- const char *filter="msg_id == 23 && size >= 2048";
- const char *tmp;
- struct lttng_log_level_rule *log_level_rule = NULL;
- const struct lttng_log_level_rule *log_level_rule_return = NULL;
- struct lttng_payload payload;
-
- diag("Testing lttng_event_rule_user_python_logging.");
-
- lttng_payload_init(&payload);
-
- log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
- LTTNG_ASSERT(log_level_rule);
-
- python_logging = lttng_event_rule_python_logging_create();
- ok(python_logging, "python_logging object.");
-
- status = lttng_event_rule_python_logging_set_name_pattern(python_logging, pattern);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
- status = lttng_event_rule_python_logging_get_name_pattern(python_logging, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
- ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
-
- status = lttng_event_rule_python_logging_set_filter(python_logging, filter);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
- status = lttng_event_rule_python_logging_get_filter(python_logging, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
- ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
-
- status = lttng_event_rule_python_logging_get_log_level_rule(python_logging, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
-
- status = lttng_event_rule_python_logging_set_log_level_rule(
- python_logging, log_level_rule);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
- status = lttng_event_rule_python_logging_get_log_level_rule(
- python_logging, &log_level_rule_return);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
-
- ok(lttng_event_rule_serialize(python_logging, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &python_logging_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(python_logging, python_logging_from_buffer), "serialized and from buffer are equal.");
-
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(python_logging);
- lttng_event_rule_destroy(python_logging_from_buffer);
- lttng_log_level_rule_destroy(log_level_rule);
-}
-
-static void test_event_rule_userspace_probe(void)
-{
- struct lttng_event_rule *uprobe = NULL;
- struct lttng_event_rule *uprobe_from_buffer = NULL;
- struct lttng_userspace_probe_location_lookup_method *lookup_method =
- NULL;
- struct lttng_userspace_probe_location *probe_location = NULL;
- const struct lttng_userspace_probe_location *probe_location_tmp = NULL;
- enum lttng_event_rule_status status;
-
- const char *probe_name = "my_probe.";
- const char *tmp;
- struct lttng_payload payload;
-
- diag("Event rule uprobe.");
-
- lookup_method = lttng_userspace_probe_location_lookup_method_function_elf_create();
- if (!lookup_method) {
- fail("Setup error on userspace probe lookup method creation.");
- goto end;
- }
-
- probe_location = lttng_userspace_probe_location_function_create(
- "/proc/self/exe",
- "lttng_userspace_probe_location_tracepoint_create",
- lookup_method);
- if (!probe_location) {
- fail("Setup error on userspace probe location creation.");
- goto end;
- }
-
- /* Ownership transferred to the probe location function object. */
- lookup_method = NULL;
-
- lttng_payload_init(&payload);
-
- uprobe = lttng_event_rule_kernel_uprobe_create(probe_location);
- ok(uprobe, "uprobe event rule object creation.");
-
- status = lttng_event_rule_kernel_uprobe_get_location(
- uprobe, &probe_location_tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "Getting uprobe event rule location.");
- ok(lttng_userspace_probe_location_is_equal(
- probe_location, probe_location_tmp),
- "Location is equal.");
-
- status = lttng_event_rule_kernel_uprobe_set_event_name(uprobe, probe_name);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "Setting uprobe event rule name: %s.", probe_name);
- status = lttng_event_rule_kernel_uprobe_get_event_name(uprobe, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Getting uprobe name.");
- ok(!strcmp(probe_name, tmp), "Uprobe name are equal.");
-
- ok(lttng_event_rule_serialize(uprobe, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &uprobe_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(uprobe, uprobe_from_buffer),
- "serialized and from buffer are equal.");
-
-end:
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(uprobe);
- lttng_event_rule_destroy(uprobe_from_buffer);
- lttng_userspace_probe_location_destroy(probe_location);
- lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
-}
-
-static void test_event_rule_kernel_probe_by_location(
- const struct lttng_kernel_probe_location *location)
-{
- struct lttng_event_rule *kprobe = NULL;
- struct lttng_event_rule *kprobe_from_buffer = NULL;
- enum lttng_event_rule_status status;
- const struct lttng_kernel_probe_location *_location;
-
- const char *probe_name = "my_probe";
- const char *tmp;
- struct lttng_payload payload;
-
- diag("Event rule kprobe for location type %d.",
- lttng_kernel_probe_location_get_type(location));
-
- lttng_payload_init(&payload);
-
- kprobe = lttng_event_rule_kernel_kprobe_create(location);
- ok(kprobe, "kprobe event rule object creation.");
-
- status = lttng_event_rule_kernel_kprobe_get_location(kprobe, &_location);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "Getting kprobe event rule location.");
- ok(lttng_kernel_probe_location_is_equal(location, _location), "Locations are equal.");
-
- status = lttng_event_rule_kernel_kprobe_set_event_name(kprobe, probe_name);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK,
- "Setting kprobe event rule name: %s.", probe_name);
- status = lttng_event_rule_kernel_kprobe_get_event_name(kprobe, &tmp);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Getting kprobe name.");
- ok(!strcmp(probe_name, tmp), "kprobe name are equal.");
-
- ok(lttng_event_rule_serialize(kprobe, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_event_rule_create_from_payload(
- &view, &kprobe_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_event_rule_is_equal(kprobe, kprobe_from_buffer),
- "serialized and from buffer are equal.");
-
- lttng_payload_reset(&payload);
- lttng_event_rule_destroy(kprobe);
- lttng_event_rule_destroy(kprobe_from_buffer);
-}
-
-static void test_event_rule_kernel_probe(void)
-{
- struct lttng_kernel_probe_location *address_location = NULL;
- struct lttng_kernel_probe_location *symbol_location = NULL;
-
- address_location = lttng_kernel_probe_location_address_create(50);
- symbol_location = lttng_kernel_probe_location_symbol_create("une_bonne", 50);
- LTTNG_ASSERT(address_location);
- LTTNG_ASSERT(symbol_location);
-
- test_event_rule_kernel_probe_by_location(address_location);
- test_event_rule_kernel_probe_by_location(symbol_location);
-
- lttng_kernel_probe_location_destroy(address_location);
- lttng_kernel_probe_location_destroy(symbol_location);
-}
-
-static void test_set_event_rule_log_level_rules(
- struct lttng_event_rule *event_rule,
- event_rule_set_log_level set_log_level,
- int log_level,
- enum lttng_event_rule_status *exactly_status,
- enum lttng_event_rule_status *as_severe_status)
-{
- struct lttng_log_level_rule *log_level_rule;
-
- log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(
- log_level);
- LTTNG_ASSERT(log_level_rule);
-
- *as_severe_status = set_log_level(
- event_rule, log_level_rule);
- lttng_log_level_rule_destroy(log_level_rule);
-
- log_level_rule = lttng_log_level_rule_exactly_create(log_level);
- LTTNG_ASSERT(log_level_rule);
-
- *exactly_status = set_log_level(
- event_rule, log_level_rule);
- lttng_log_level_rule_destroy(log_level_rule);
-}
-
-static void test_event_rule_log_level_generic(enum lttng_event_rule_type event_rule_type,
- log_level_name_getter get_log_level_name,
- event_rule_create create_event_rule,
- event_rule_set_log_level set_log_level,
- const int tagged_log_level_values[],
- size_t tagged_log_level_values_count,
- const int valid_log_level_values[],
- size_t valid_log_level_values_count,
- const int invalid_log_level_values[],
- size_t invalid_log_level_values_count)
-{
- size_t i;
- struct lttng_event_rule *rule;
- enum lttng_event_rule_status er_exactly_status, er_as_severe_status;
- const char *event_rule_type_str = lttng_event_rule_type_str(event_rule_type);
-
-
- diag("Test %s event rule + log level rule", event_rule_type_str);
-
- rule = create_event_rule();
- LTTNG_ASSERT(rule);
-
- for (i = 0; i < tagged_log_level_values_count; i++) {
- const int tagged_log_level_value = tagged_log_level_values[i];
-
- test_set_event_rule_log_level_rules(rule, set_log_level,
- tagged_log_level_value,
- &er_exactly_status, &er_as_severe_status);
- ok(er_exactly_status == LTTNG_EVENT_RULE_STATUS_OK,
- "Log level rule \"exactly\" accepted by %s event rule: level = %s",
- event_rule_type_str,
- get_log_level_name(
- tagged_log_level_value));
- ok(er_as_severe_status == LTTNG_EVENT_RULE_STATUS_OK,
- "Log level rule \"as least as severe as\" accepted by %s event rule: level = %s",
- event_rule_type_str,
- get_log_level_name(
- tagged_log_level_value));
- }
-
- for (i = 0; i < valid_log_level_values_count; i++) {
- const int valid_log_level_value = valid_log_level_values[i];
-
- test_set_event_rule_log_level_rules(rule, set_log_level,
- valid_log_level_value,
- &er_exactly_status, &er_as_severe_status);
- ok(er_exactly_status == LTTNG_EVENT_RULE_STATUS_OK,
- "Log level rule \"exactly\" accepted by %s event rule: level = %d",
- event_rule_type_str,
- valid_log_level_value);
- ok(er_as_severe_status == LTTNG_EVENT_RULE_STATUS_OK,
- "Log level rule \"as least as severe as\" accepted by %s event rule: level = %d",
- event_rule_type_str,
- valid_log_level_value);
- }
-
- for (i = 0; i < invalid_log_level_values_count; i++) {
- const int invalid_log_level_value = invalid_log_level_values[i];
-
- test_set_event_rule_log_level_rules(rule, set_log_level,
- invalid_log_level_value,
- &er_exactly_status, &er_as_severe_status);
- ok(er_exactly_status == LTTNG_EVENT_RULE_STATUS_INVALID,
- "Log level rule \"exactly\" rejected by %s event rule: level = %d",
- event_rule_type_str,
- invalid_log_level_value);
- ok(er_as_severe_status == LTTNG_EVENT_RULE_STATUS_INVALID,
- "Log level rule \"as least as severe as\" rejected by %s event rule: level = %d",
- event_rule_type_str,
- invalid_log_level_value);
- }
-
- lttng_event_rule_destroy(rule);
-}
-
-static void test_event_rule_log_level_ust(void)
-{
- const int tagged_log_level_values[] = {
- LTTNG_LOGLEVEL_EMERG,
- LTTNG_LOGLEVEL_ALERT,
- LTTNG_LOGLEVEL_CRIT,
- LTTNG_LOGLEVEL_ERR,
- LTTNG_LOGLEVEL_WARNING,
- LTTNG_LOGLEVEL_NOTICE,
- LTTNG_LOGLEVEL_INFO,
- LTTNG_LOGLEVEL_DEBUG_SYSTEM,
- LTTNG_LOGLEVEL_DEBUG_PROGRAM,
- LTTNG_LOGLEVEL_DEBUG_PROCESS,
- LTTNG_LOGLEVEL_DEBUG_MODULE,
- LTTNG_LOGLEVEL_DEBUG_UNIT,
- LTTNG_LOGLEVEL_DEBUG_FUNCTION,
- LTTNG_LOGLEVEL_DEBUG_LINE,
- LTTNG_LOGLEVEL_DEBUG,
- };
- const int invalid_log_level_values[] = {
- -1980,
- 1995,
- LTTNG_LOGLEVEL_DEBUG + 1,
- LTTNG_LOGLEVEL_EMERG - 1,
- };
-
- test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT,
- loglevel_value_to_name,
- lttng_event_rule_user_tracepoint_create,
- lttng_event_rule_user_tracepoint_set_log_level_rule,
- tagged_log_level_values,
- ARRAY_SIZE(tagged_log_level_values), NULL, 0,
- invalid_log_level_values,
- ARRAY_SIZE(invalid_log_level_values));
-}
-
-static void test_event_rule_log_level_jul(void)
-{
- const int tagged_log_level_values[] = {
- LTTNG_LOGLEVEL_JUL_OFF,
- LTTNG_LOGLEVEL_JUL_SEVERE,
- LTTNG_LOGLEVEL_JUL_WARNING,
- LTTNG_LOGLEVEL_JUL_INFO,
- LTTNG_LOGLEVEL_JUL_CONFIG,
- LTTNG_LOGLEVEL_JUL_FINE,
- LTTNG_LOGLEVEL_JUL_FINER,
- LTTNG_LOGLEVEL_JUL_FINEST,
- LTTNG_LOGLEVEL_JUL_ALL,
- };
- const int valid_log_level_values[] = {
- 0,
- -1980,
- 1995
- };
-
- test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_JUL_LOGGING,
- loglevel_jul_value_to_name,
- lttng_event_rule_jul_logging_create,
- lttng_event_rule_jul_logging_set_log_level_rule,
- tagged_log_level_values,
- ARRAY_SIZE(tagged_log_level_values),
- valid_log_level_values,
- ARRAY_SIZE(valid_log_level_values), NULL, 0);
-}
-
-static void test_event_rule_log_level_log4j(void)
-{
- const int tagged_log_level_values[] = {
- LTTNG_LOGLEVEL_LOG4J_OFF,
- LTTNG_LOGLEVEL_LOG4J_FATAL,
- LTTNG_LOGLEVEL_LOG4J_ERROR,
- LTTNG_LOGLEVEL_LOG4J_WARN,
- LTTNG_LOGLEVEL_LOG4J_INFO,
- LTTNG_LOGLEVEL_LOG4J_DEBUG,
- LTTNG_LOGLEVEL_LOG4J_TRACE,
- LTTNG_LOGLEVEL_LOG4J_ALL,
- };
- const int valid_log_level_values[] = {
- 0
- -1980,
- 1995
- };
-
- test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING,
- loglevel_log4j_value_to_name,
- lttng_event_rule_log4j_logging_create,
- lttng_event_rule_log4j_logging_set_log_level_rule,
- tagged_log_level_values,
- ARRAY_SIZE(tagged_log_level_values),
- valid_log_level_values,
- ARRAY_SIZE(valid_log_level_values), NULL, 0);
-}
-
-static void test_event_rule_log_level_python(void)
-{
- const int tagged_log_level_values[] = {
- LTTNG_LOGLEVEL_PYTHON_CRITICAL,
- LTTNG_LOGLEVEL_PYTHON_ERROR,
- LTTNG_LOGLEVEL_PYTHON_WARNING,
- LTTNG_LOGLEVEL_PYTHON_INFO,
- LTTNG_LOGLEVEL_PYTHON_DEBUG,
- LTTNG_LOGLEVEL_PYTHON_NOTSET,
- };
- const int valid_log_level_values[] = {
- 45,
- 35,
- 0,
- -657,
- };
-
- test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING,
- loglevel_python_value_to_name,
- lttng_event_rule_python_logging_create,
- lttng_event_rule_python_logging_set_log_level_rule,
- tagged_log_level_values,
- ARRAY_SIZE(tagged_log_level_values),
- valid_log_level_values,
- ARRAY_SIZE(valid_log_level_values),
- NULL, 0);
-}
-
-int main(int argc, const char *argv[])
-{
- plan_tests(NUM_TESTS);
- test_event_rule_kernel_tracepoint();
- test_event_rule_user_tracepoint();
- test_event_rule_syscall();
- test_event_rule_userspace_probe();
- test_event_rule_kernel_probe();
- test_event_rule_log4j_logging();
- test_event_rule_jul_logging();
- test_event_rule_python_logging();
- test_event_rule_log_level_ust();
- test_event_rule_log_level_jul();
- test_event_rule_log_level_log4j();
- test_event_rule_log_level_python();
- return exit_status();
-}
--- /dev/null
+/*
+ * Unit tests for the notification API.
+ *
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/domain.h>
+#include <lttng/event-rule/jul-logging-internal.h>
+#include <lttng/event-rule/jul-logging.h>
+#include <lttng/event-rule/kernel-kprobe-internal.h>
+#include <lttng/event-rule/kernel-kprobe.h>
+#include <lttng/event-rule/kernel-syscall-internal.h>
+#include <lttng/event-rule/kernel-syscall.h>
+#include <lttng/event-rule/python-logging-internal.h>
+#include <lttng/event-rule/python-logging.h>
+#include <lttng/event-rule/kernel-tracepoint-internal.h>
+#include <lttng/event-rule/kernel-tracepoint.h>
+#include <lttng/event-rule/kernel-uprobe-internal.h>
+#include <lttng/event-rule/kernel-uprobe.h>
+#include <lttng/event-rule/user-tracepoint-internal.h>
+#include <lttng/event-rule/user-tracepoint.h>
+#include <lttng/event.h>
+#include <lttng/kernel-probe-internal.h>
+#include <lttng/kernel-probe.h>
+#include <lttng/userspace-probe-internal.h>
+#include <lttng/userspace-probe.h>
+#include "bin/lttng/loglevel.h"
+
+/* For error.h. */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 212
+
+struct tracepoint_test {
+ enum lttng_domain_type type;
+ bool support_name_pattern_exclusion;
+};
+
+typedef const char *(*log_level_name_getter)(int log_level);
+
+typedef struct lttng_event_rule *(*event_rule_create)(void);
+typedef enum lttng_event_rule_status (*event_rule_set_log_level)(
+ struct lttng_event_rule *rule,
+ const struct lttng_log_level_rule *log_level_rule);
+
+static
+void test_event_rule_kernel_tracepoint(void)
+{
+ struct lttng_event_rule *tracepoint = NULL;
+ struct lttng_event_rule *tracepoint_from_buffer = NULL;
+ enum lttng_event_rule_status status;
+ const char *pattern="my_event_*";
+ const char *filter="msg_id == 23 && size >= 2048";
+ const char *tmp;
+ struct lttng_payload payload;
+
+ diag("Testing lttng_event_rule_kernel_tracepoint.");
+
+ lttng_payload_init(&payload);
+
+ tracepoint = lttng_event_rule_kernel_tracepoint_create();
+ ok(tracepoint, "tracepoint object.");
+
+ status = lttng_event_rule_kernel_tracepoint_set_name_pattern(tracepoint, pattern);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
+ status = lttng_event_rule_kernel_tracepoint_get_name_pattern(tracepoint, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
+ ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
+
+ status = lttng_event_rule_kernel_tracepoint_set_filter(tracepoint, filter);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
+ status = lttng_event_rule_kernel_tracepoint_get_filter(tracepoint, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
+ ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
+
+ ok(lttng_event_rule_serialize(tracepoint, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &tracepoint_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(tracepoint, tracepoint_from_buffer), "serialized and from buffer are equal.");
+
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(tracepoint);
+ lttng_event_rule_destroy(tracepoint_from_buffer);
+}
+
+static
+void test_event_rule_user_tracepoint(void)
+{
+ int i;
+ unsigned int count;
+ struct lttng_event_rule *tracepoint = NULL;
+ struct lttng_event_rule *tracepoint_from_buffer = NULL;
+ enum lttng_event_rule_status status;
+ const char *pattern="my_event_*";
+ const char *filter="msg_id == 23 && size >= 2048";
+ const char *tmp;
+ const char *name_pattern_exclusions[] = {"my_event_test1", "my_event_test2" ,"my_event_test3"};
+ struct lttng_log_level_rule *log_level_rule = NULL;
+ const struct lttng_log_level_rule *log_level_rule_return = NULL;
+ struct lttng_payload payload;
+
+ diag("Testing lttng_event_rule_user_tracepoint.");
+
+ lttng_payload_init(&payload);
+
+ log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
+ LTTNG_ASSERT(log_level_rule);
+
+ tracepoint = lttng_event_rule_user_tracepoint_create();
+ ok(tracepoint, "user tracepoint object.");
+
+ status = lttng_event_rule_user_tracepoint_set_name_pattern(tracepoint, pattern);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
+ status = lttng_event_rule_user_tracepoint_get_name_pattern(tracepoint, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
+ ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
+
+ status = lttng_event_rule_user_tracepoint_set_filter(tracepoint, filter);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
+ status = lttng_event_rule_user_tracepoint_get_filter(tracepoint, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
+ ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
+
+ status = lttng_event_rule_user_tracepoint_get_log_level_rule(tracepoint, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
+
+ status = lttng_event_rule_user_tracepoint_set_log_level_rule(
+ tracepoint, log_level_rule);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
+ status = lttng_event_rule_user_tracepoint_get_log_level_rule(
+ tracepoint, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
+
+ /* Name pattern exclusions */
+ for (i = 0; i < 3; i++) {
+ status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
+ tracepoint, name_pattern_exclusions[i]);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "setting name pattern exclusions \"%s\"",
+ name_pattern_exclusions[i]);
+ }
+
+ status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
+ tracepoint, &count);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "getting name pattern exclusion count.");
+ ok(count == 3, "count is %d/3", count);
+
+ for (i = 0; i < count; i++) {
+ status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
+ tracepoint, i, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "getting name pattern exclusion at index %d.",
+ i);
+ ok(!strncmp(name_pattern_exclusions[i], tmp,
+ strlen(name_pattern_exclusions[i])),
+ "%s == %s.", tmp, name_pattern_exclusions[i]);
+ }
+
+ ok(lttng_event_rule_serialize(tracepoint, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &tracepoint_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(tracepoint, tracepoint_from_buffer), "serialized and from buffer are equal.");
+
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(tracepoint);
+ lttng_event_rule_destroy(tracepoint_from_buffer);
+ lttng_log_level_rule_destroy(log_level_rule);
+}
+
+static void test_event_rule_syscall(void)
+{
+ struct lttng_event_rule *syscall = NULL;
+ struct lttng_event_rule *syscall_from_buffer = NULL;
+ enum lttng_event_rule_status status;
+ const char *pattern = "my_event_*";
+ const char *filter = "msg_id == 23 && size >= 2048";
+ const char *tmp;
+ struct lttng_payload payload;
+
+ diag("Event rule syscall.");
+
+ lttng_payload_init(&payload);
+
+ syscall = lttng_event_rule_kernel_syscall_create(LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY);
+ ok(syscall, "syscall object.");
+
+ status = lttng_event_rule_kernel_syscall_set_name_pattern(syscall, pattern);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
+ status = lttng_event_rule_kernel_syscall_get_name_pattern(syscall, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
+ ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
+
+ status = lttng_event_rule_kernel_syscall_set_filter(syscall, filter);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
+ status = lttng_event_rule_kernel_syscall_get_filter(syscall, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
+ ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
+
+ ok(lttng_event_rule_serialize(syscall, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &syscall_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(syscall, syscall_from_buffer),
+ "serialized and from buffer are equal.");
+
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(syscall);
+ lttng_event_rule_destroy(syscall_from_buffer);
+}
+
+static
+void test_event_rule_jul_logging(void)
+{
+ struct lttng_event_rule *jul_logging = NULL;
+ struct lttng_event_rule *jul_logging_from_buffer = NULL;
+ enum lttng_event_rule_status status;
+ const char *pattern="my_event_*";
+ const char *filter="msg_id == 23 && size >= 2048";
+ const char *tmp;
+ struct lttng_log_level_rule *log_level_rule = NULL;
+ const struct lttng_log_level_rule *log_level_rule_return = NULL;
+ struct lttng_payload payload;
+
+ diag("Testing lttng_event_rule_user_jul_logging.");
+
+ lttng_payload_init(&payload);
+
+ log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
+ LTTNG_ASSERT(log_level_rule);
+
+ jul_logging = lttng_event_rule_jul_logging_create();
+ ok(jul_logging, "jul_logging object.");
+
+ status = lttng_event_rule_jul_logging_set_name_pattern(jul_logging, pattern);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
+ status = lttng_event_rule_jul_logging_get_name_pattern(jul_logging, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
+ ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
+
+ status = lttng_event_rule_jul_logging_set_filter(jul_logging, filter);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
+ status = lttng_event_rule_jul_logging_get_filter(jul_logging, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
+ ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
+
+ status = lttng_event_rule_jul_logging_get_log_level_rule(jul_logging, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
+
+ status = lttng_event_rule_jul_logging_set_log_level_rule(
+ jul_logging, log_level_rule);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
+ status = lttng_event_rule_jul_logging_get_log_level_rule(
+ jul_logging, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
+
+ ok(lttng_event_rule_serialize(jul_logging, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &jul_logging_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(jul_logging, jul_logging_from_buffer), "serialized and from buffer are equal.");
+
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(jul_logging);
+ lttng_event_rule_destroy(jul_logging_from_buffer);
+ lttng_log_level_rule_destroy(log_level_rule);
+}
+
+static
+void test_event_rule_log4j_logging(void)
+{
+ struct lttng_event_rule *log4j_logging = NULL;
+ struct lttng_event_rule *log4j_logging_from_buffer = NULL;
+ enum lttng_event_rule_status status;
+ const char *pattern="my_event_*";
+ const char *filter="msg_id == 23 && size >= 2048";
+ const char *tmp;
+ struct lttng_log_level_rule *log_level_rule = NULL;
+ const struct lttng_log_level_rule *log_level_rule_return = NULL;
+ struct lttng_payload payload;
+
+ diag("Testing lttng_event_rule_user_log4j_logging.");
+
+ lttng_payload_init(&payload);
+
+ log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
+ LTTNG_ASSERT(log_level_rule);
+
+ log4j_logging = lttng_event_rule_log4j_logging_create();
+ ok(log4j_logging, "log4j_logging object.");
+
+ status = lttng_event_rule_log4j_logging_set_name_pattern(log4j_logging, pattern);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
+ status = lttng_event_rule_log4j_logging_get_name_pattern(log4j_logging, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
+ ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
+
+ status = lttng_event_rule_log4j_logging_set_filter(log4j_logging, filter);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
+ status = lttng_event_rule_log4j_logging_get_filter(log4j_logging, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
+ ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
+
+ status = lttng_event_rule_log4j_logging_get_log_level_rule(log4j_logging, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
+
+ status = lttng_event_rule_log4j_logging_set_log_level_rule(
+ log4j_logging, log_level_rule);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
+ status = lttng_event_rule_log4j_logging_get_log_level_rule(
+ log4j_logging, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
+
+ ok(lttng_event_rule_serialize(log4j_logging, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &log4j_logging_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(log4j_logging, log4j_logging_from_buffer), "serialized and from buffer are equal.");
+
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(log4j_logging);
+ lttng_event_rule_destroy(log4j_logging_from_buffer);
+ lttng_log_level_rule_destroy(log_level_rule);
+}
+
+static
+void test_event_rule_python_logging(void)
+{
+ struct lttng_event_rule *python_logging = NULL;
+ struct lttng_event_rule *python_logging_from_buffer = NULL;
+ enum lttng_event_rule_status status;
+ const char *pattern="my_event_*";
+ const char *filter="msg_id == 23 && size >= 2048";
+ const char *tmp;
+ struct lttng_log_level_rule *log_level_rule = NULL;
+ const struct lttng_log_level_rule *log_level_rule_return = NULL;
+ struct lttng_payload payload;
+
+ diag("Testing lttng_event_rule_user_python_logging.");
+
+ lttng_payload_init(&payload);
+
+ log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
+ LTTNG_ASSERT(log_level_rule);
+
+ python_logging = lttng_event_rule_python_logging_create();
+ ok(python_logging, "python_logging object.");
+
+ status = lttng_event_rule_python_logging_set_name_pattern(python_logging, pattern);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting pattern.");
+ status = lttng_event_rule_python_logging_get_name_pattern(python_logging, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting pattern.");
+ ok(!strncmp(pattern, tmp, strlen(pattern)), "pattern is equal.");
+
+ status = lttng_event_rule_python_logging_set_filter(python_logging, filter);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting filter.");
+ status = lttng_event_rule_python_logging_get_filter(python_logging, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
+ ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
+
+ status = lttng_event_rule_python_logging_get_log_level_rule(python_logging, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
+
+ status = lttng_event_rule_python_logging_set_log_level_rule(
+ python_logging, log_level_rule);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
+ status = lttng_event_rule_python_logging_get_log_level_rule(
+ python_logging, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
+
+ ok(lttng_event_rule_serialize(python_logging, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &python_logging_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(python_logging, python_logging_from_buffer), "serialized and from buffer are equal.");
+
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(python_logging);
+ lttng_event_rule_destroy(python_logging_from_buffer);
+ lttng_log_level_rule_destroy(log_level_rule);
+}
+
+static void test_event_rule_userspace_probe(void)
+{
+ struct lttng_event_rule *uprobe = NULL;
+ struct lttng_event_rule *uprobe_from_buffer = NULL;
+ struct lttng_userspace_probe_location_lookup_method *lookup_method =
+ NULL;
+ struct lttng_userspace_probe_location *probe_location = NULL;
+ const struct lttng_userspace_probe_location *probe_location_tmp = NULL;
+ enum lttng_event_rule_status status;
+
+ const char *probe_name = "my_probe.";
+ const char *tmp;
+ struct lttng_payload payload;
+
+ diag("Event rule uprobe.");
+
+ lookup_method = lttng_userspace_probe_location_lookup_method_function_elf_create();
+ if (!lookup_method) {
+ fail("Setup error on userspace probe lookup method creation.");
+ goto end;
+ }
+
+ probe_location = lttng_userspace_probe_location_function_create(
+ "/proc/self/exe",
+ "lttng_userspace_probe_location_tracepoint_create",
+ lookup_method);
+ if (!probe_location) {
+ fail("Setup error on userspace probe location creation.");
+ goto end;
+ }
+
+ /* Ownership transferred to the probe location function object. */
+ lookup_method = NULL;
+
+ lttng_payload_init(&payload);
+
+ uprobe = lttng_event_rule_kernel_uprobe_create(probe_location);
+ ok(uprobe, "uprobe event rule object creation.");
+
+ status = lttng_event_rule_kernel_uprobe_get_location(
+ uprobe, &probe_location_tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Getting uprobe event rule location.");
+ ok(lttng_userspace_probe_location_is_equal(
+ probe_location, probe_location_tmp),
+ "Location is equal.");
+
+ status = lttng_event_rule_kernel_uprobe_set_event_name(uprobe, probe_name);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Setting uprobe event rule name: %s.", probe_name);
+ status = lttng_event_rule_kernel_uprobe_get_event_name(uprobe, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Getting uprobe name.");
+ ok(!strcmp(probe_name, tmp), "Uprobe name are equal.");
+
+ ok(lttng_event_rule_serialize(uprobe, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &uprobe_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(uprobe, uprobe_from_buffer),
+ "serialized and from buffer are equal.");
+
+end:
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(uprobe);
+ lttng_event_rule_destroy(uprobe_from_buffer);
+ lttng_userspace_probe_location_destroy(probe_location);
+ lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
+}
+
+static void test_event_rule_kernel_probe_by_location(
+ const struct lttng_kernel_probe_location *location)
+{
+ struct lttng_event_rule *kprobe = NULL;
+ struct lttng_event_rule *kprobe_from_buffer = NULL;
+ enum lttng_event_rule_status status;
+ const struct lttng_kernel_probe_location *_location;
+
+ const char *probe_name = "my_probe";
+ const char *tmp;
+ struct lttng_payload payload;
+
+ diag("Event rule kprobe for location type %d.",
+ lttng_kernel_probe_location_get_type(location));
+
+ lttng_payload_init(&payload);
+
+ kprobe = lttng_event_rule_kernel_kprobe_create(location);
+ ok(kprobe, "kprobe event rule object creation.");
+
+ status = lttng_event_rule_kernel_kprobe_get_location(kprobe, &_location);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Getting kprobe event rule location.");
+ ok(lttng_kernel_probe_location_is_equal(location, _location), "Locations are equal.");
+
+ status = lttng_event_rule_kernel_kprobe_set_event_name(kprobe, probe_name);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Setting kprobe event rule name: %s.", probe_name);
+ status = lttng_event_rule_kernel_kprobe_get_event_name(kprobe, &tmp);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Getting kprobe name.");
+ ok(!strcmp(probe_name, tmp), "kprobe name are equal.");
+
+ ok(lttng_event_rule_serialize(kprobe, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_event_rule_create_from_payload(
+ &view, &kprobe_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_event_rule_is_equal(kprobe, kprobe_from_buffer),
+ "serialized and from buffer are equal.");
+
+ lttng_payload_reset(&payload);
+ lttng_event_rule_destroy(kprobe);
+ lttng_event_rule_destroy(kprobe_from_buffer);
+}
+
+static void test_event_rule_kernel_probe(void)
+{
+ struct lttng_kernel_probe_location *address_location = NULL;
+ struct lttng_kernel_probe_location *symbol_location = NULL;
+
+ address_location = lttng_kernel_probe_location_address_create(50);
+ symbol_location = lttng_kernel_probe_location_symbol_create("une_bonne", 50);
+ LTTNG_ASSERT(address_location);
+ LTTNG_ASSERT(symbol_location);
+
+ test_event_rule_kernel_probe_by_location(address_location);
+ test_event_rule_kernel_probe_by_location(symbol_location);
+
+ lttng_kernel_probe_location_destroy(address_location);
+ lttng_kernel_probe_location_destroy(symbol_location);
+}
+
+static void test_set_event_rule_log_level_rules(
+ struct lttng_event_rule *event_rule,
+ event_rule_set_log_level set_log_level,
+ int log_level,
+ enum lttng_event_rule_status *exactly_status,
+ enum lttng_event_rule_status *as_severe_status)
+{
+ struct lttng_log_level_rule *log_level_rule;
+
+ log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(
+ log_level);
+ LTTNG_ASSERT(log_level_rule);
+
+ *as_severe_status = set_log_level(
+ event_rule, log_level_rule);
+ lttng_log_level_rule_destroy(log_level_rule);
+
+ log_level_rule = lttng_log_level_rule_exactly_create(log_level);
+ LTTNG_ASSERT(log_level_rule);
+
+ *exactly_status = set_log_level(
+ event_rule, log_level_rule);
+ lttng_log_level_rule_destroy(log_level_rule);
+}
+
+static void test_event_rule_log_level_generic(enum lttng_event_rule_type event_rule_type,
+ log_level_name_getter get_log_level_name,
+ event_rule_create create_event_rule,
+ event_rule_set_log_level set_log_level,
+ const int tagged_log_level_values[],
+ size_t tagged_log_level_values_count,
+ const int valid_log_level_values[],
+ size_t valid_log_level_values_count,
+ const int invalid_log_level_values[],
+ size_t invalid_log_level_values_count)
+{
+ size_t i;
+ struct lttng_event_rule *rule;
+ enum lttng_event_rule_status er_exactly_status, er_as_severe_status;
+ const char *event_rule_type_str = lttng_event_rule_type_str(event_rule_type);
+
+
+ diag("Test %s event rule + log level rule", event_rule_type_str);
+
+ rule = create_event_rule();
+ LTTNG_ASSERT(rule);
+
+ for (i = 0; i < tagged_log_level_values_count; i++) {
+ const int tagged_log_level_value = tagged_log_level_values[i];
+
+ test_set_event_rule_log_level_rules(rule, set_log_level,
+ tagged_log_level_value,
+ &er_exactly_status, &er_as_severe_status);
+ ok(er_exactly_status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Log level rule \"exactly\" accepted by %s event rule: level = %s",
+ event_rule_type_str,
+ get_log_level_name(
+ tagged_log_level_value));
+ ok(er_as_severe_status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Log level rule \"as least as severe as\" accepted by %s event rule: level = %s",
+ event_rule_type_str,
+ get_log_level_name(
+ tagged_log_level_value));
+ }
+
+ for (i = 0; i < valid_log_level_values_count; i++) {
+ const int valid_log_level_value = valid_log_level_values[i];
+
+ test_set_event_rule_log_level_rules(rule, set_log_level,
+ valid_log_level_value,
+ &er_exactly_status, &er_as_severe_status);
+ ok(er_exactly_status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Log level rule \"exactly\" accepted by %s event rule: level = %d",
+ event_rule_type_str,
+ valid_log_level_value);
+ ok(er_as_severe_status == LTTNG_EVENT_RULE_STATUS_OK,
+ "Log level rule \"as least as severe as\" accepted by %s event rule: level = %d",
+ event_rule_type_str,
+ valid_log_level_value);
+ }
+
+ for (i = 0; i < invalid_log_level_values_count; i++) {
+ const int invalid_log_level_value = invalid_log_level_values[i];
+
+ test_set_event_rule_log_level_rules(rule, set_log_level,
+ invalid_log_level_value,
+ &er_exactly_status, &er_as_severe_status);
+ ok(er_exactly_status == LTTNG_EVENT_RULE_STATUS_INVALID,
+ "Log level rule \"exactly\" rejected by %s event rule: level = %d",
+ event_rule_type_str,
+ invalid_log_level_value);
+ ok(er_as_severe_status == LTTNG_EVENT_RULE_STATUS_INVALID,
+ "Log level rule \"as least as severe as\" rejected by %s event rule: level = %d",
+ event_rule_type_str,
+ invalid_log_level_value);
+ }
+
+ lttng_event_rule_destroy(rule);
+}
+
+static void test_event_rule_log_level_ust(void)
+{
+ const int tagged_log_level_values[] = {
+ LTTNG_LOGLEVEL_EMERG,
+ LTTNG_LOGLEVEL_ALERT,
+ LTTNG_LOGLEVEL_CRIT,
+ LTTNG_LOGLEVEL_ERR,
+ LTTNG_LOGLEVEL_WARNING,
+ LTTNG_LOGLEVEL_NOTICE,
+ LTTNG_LOGLEVEL_INFO,
+ LTTNG_LOGLEVEL_DEBUG_SYSTEM,
+ LTTNG_LOGLEVEL_DEBUG_PROGRAM,
+ LTTNG_LOGLEVEL_DEBUG_PROCESS,
+ LTTNG_LOGLEVEL_DEBUG_MODULE,
+ LTTNG_LOGLEVEL_DEBUG_UNIT,
+ LTTNG_LOGLEVEL_DEBUG_FUNCTION,
+ LTTNG_LOGLEVEL_DEBUG_LINE,
+ LTTNG_LOGLEVEL_DEBUG,
+ };
+ const int invalid_log_level_values[] = {
+ -1980,
+ 1995,
+ LTTNG_LOGLEVEL_DEBUG + 1,
+ LTTNG_LOGLEVEL_EMERG - 1,
+ };
+
+ test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT,
+ loglevel_value_to_name,
+ lttng_event_rule_user_tracepoint_create,
+ lttng_event_rule_user_tracepoint_set_log_level_rule,
+ tagged_log_level_values,
+ ARRAY_SIZE(tagged_log_level_values), NULL, 0,
+ invalid_log_level_values,
+ ARRAY_SIZE(invalid_log_level_values));
+}
+
+static void test_event_rule_log_level_jul(void)
+{
+ const int tagged_log_level_values[] = {
+ LTTNG_LOGLEVEL_JUL_OFF,
+ LTTNG_LOGLEVEL_JUL_SEVERE,
+ LTTNG_LOGLEVEL_JUL_WARNING,
+ LTTNG_LOGLEVEL_JUL_INFO,
+ LTTNG_LOGLEVEL_JUL_CONFIG,
+ LTTNG_LOGLEVEL_JUL_FINE,
+ LTTNG_LOGLEVEL_JUL_FINER,
+ LTTNG_LOGLEVEL_JUL_FINEST,
+ LTTNG_LOGLEVEL_JUL_ALL,
+ };
+ const int valid_log_level_values[] = {
+ 0,
+ -1980,
+ 1995
+ };
+
+ test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_JUL_LOGGING,
+ loglevel_jul_value_to_name,
+ lttng_event_rule_jul_logging_create,
+ lttng_event_rule_jul_logging_set_log_level_rule,
+ tagged_log_level_values,
+ ARRAY_SIZE(tagged_log_level_values),
+ valid_log_level_values,
+ ARRAY_SIZE(valid_log_level_values), NULL, 0);
+}
+
+static void test_event_rule_log_level_log4j(void)
+{
+ const int tagged_log_level_values[] = {
+ LTTNG_LOGLEVEL_LOG4J_OFF,
+ LTTNG_LOGLEVEL_LOG4J_FATAL,
+ LTTNG_LOGLEVEL_LOG4J_ERROR,
+ LTTNG_LOGLEVEL_LOG4J_WARN,
+ LTTNG_LOGLEVEL_LOG4J_INFO,
+ LTTNG_LOGLEVEL_LOG4J_DEBUG,
+ LTTNG_LOGLEVEL_LOG4J_TRACE,
+ LTTNG_LOGLEVEL_LOG4J_ALL,
+ };
+ const int valid_log_level_values[] = {
+ 0
+ -1980,
+ 1995
+ };
+
+ test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING,
+ loglevel_log4j_value_to_name,
+ lttng_event_rule_log4j_logging_create,
+ lttng_event_rule_log4j_logging_set_log_level_rule,
+ tagged_log_level_values,
+ ARRAY_SIZE(tagged_log_level_values),
+ valid_log_level_values,
+ ARRAY_SIZE(valid_log_level_values), NULL, 0);
+}
+
+static void test_event_rule_log_level_python(void)
+{
+ const int tagged_log_level_values[] = {
+ LTTNG_LOGLEVEL_PYTHON_CRITICAL,
+ LTTNG_LOGLEVEL_PYTHON_ERROR,
+ LTTNG_LOGLEVEL_PYTHON_WARNING,
+ LTTNG_LOGLEVEL_PYTHON_INFO,
+ LTTNG_LOGLEVEL_PYTHON_DEBUG,
+ LTTNG_LOGLEVEL_PYTHON_NOTSET,
+ };
+ const int valid_log_level_values[] = {
+ 45,
+ 35,
+ 0,
+ -657,
+ };
+
+ test_event_rule_log_level_generic(LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING,
+ loglevel_python_value_to_name,
+ lttng_event_rule_python_logging_create,
+ lttng_event_rule_python_logging_set_log_level_rule,
+ tagged_log_level_values,
+ ARRAY_SIZE(tagged_log_level_values),
+ valid_log_level_values,
+ ARRAY_SIZE(valid_log_level_values),
+ NULL, 0);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_event_rule_kernel_tracepoint();
+ test_event_rule_user_tracepoint();
+ test_event_rule_syscall();
+ test_event_rule_userspace_probe();
+ test_event_rule_kernel_probe();
+ test_event_rule_log4j_logging();
+ test_event_rule_jul_logging();
+ test_event_rule_python_logging();
+ test_event_rule_log_level_ust();
+ test_event_rule_log_level_jul();
+ test_event_rule_log_level_log4j();
+ test_event_rule_log_level_python();
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdarg.h>
-#include <tap/tap.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <urcu.h>
-
-#include <common/compat/directory-handle.h>
-#include <common/compat/errno.h>
-#include <common/error.h>
-#include <common/fs-handle.h>
-#include <common/fd-tracker/fd-tracker.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-/* Number of TAP tests in this file */
-#define NUM_TESTS 61
-/* 3 for stdin, stdout, and stderr */
-#define STDIO_FD_COUNT 3
-#define TRACKER_FD_LIMIT 50
-#define TMP_DIR_PATTERN "/tmp/fd-tracker-XXXXXX"
-#define TEST_UNLINK_DIRECTORY_NAME "unlinked_files"
-
-#ifdef __linux__
-#define SELF_FD_DIR "/proc/self/fd"
-#else
-/* Most Unices have /dev/fd */
-#define SELF_FD_DIR "/dev/fd"
-#endif
-
-/*
- * Count of fds, beyond stdin, stderr, stdout that were open
- * at the launch of the test. This allows the test to succeed when
- * run by automake's test runner or valgrind which both open
- * fds behind our back.
- */
-int unknown_fds_count;
-
-const char file_contents[] = "Bacon ipsum dolor amet jerky drumstick sirloin "
- "strip steak venison boudin filet mignon picanha doner shoulder. "
- "Strip steak brisket alcatra, venison beef chuck cupim pastrami. "
- "Landjaeger tri-tip salami leberkas ball tip, ham hock chuck sausage "
- "flank jerky cupim. Pig bacon chuck pancetta andouille.";
-
-static
-void get_temporary_directories(char **_test_directory, char **_unlink_directory)
-{
- int ret;
- char tmp_path_pattern[] = TMP_DIR_PATTERN;
- char *output_dir;
-
- output_dir = mkdtemp(tmp_path_pattern);
- if (!output_dir) {
- diag("Failed to create temporary path of the form %s",
- TMP_DIR_PATTERN);
- abort();
- }
-
- *_test_directory = strdup(output_dir);
- LTTNG_ASSERT(*_test_directory);
- ret = asprintf(_unlink_directory, "%s/%s", output_dir,
- TEST_UNLINK_DIRECTORY_NAME);
- if (ret < 0) {
- abort();
- }
-}
-
-static
-int fd_count(void)
-{
- DIR *dir;
- struct dirent *entry;
- int count = 0;
-
- dir = opendir(SELF_FD_DIR);
- if (!dir) {
- perror("# Failed to enumerate " SELF_FD_DIR " to count the number of used file descriptors");
- count = -1;
- goto end;
- }
-
- while ((entry = readdir(dir)) != NULL) {
- if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
- continue;
- }
- count++;
- }
- /* Don't account for the file descriptor opened by opendir(). */
- count--;
- if (closedir(dir)) {
- perror("# Failed to close test program's " SELF_FD_DIR " directory file descriptor");
- }
-end:
- return count;
-}
-
-static
-void check_fd_count(int expected_count)
-{
- int count = 0;
-
- count = fd_count();
- ok(count == expected_count, "Expected %d open file descriptors (%d are open)",
- expected_count, count);
-}
-
-static
-int noop_open(void *data, int *fds)
-{
- *fds = *((int *) data);
- return 0;
-}
-
-static
-int noop_close(void *data, int *fds)
-{
- return 0;
-}
-
-static
-void track_std_fds(struct fd_tracker *tracker)
-{
- int i;
- struct { int fd; const char *name; } files[] = {
- { .fd = fileno(stdin), .name = "stdin" },
- { .fd = fileno(stdout), .name = "stdout" },
- { .fd = fileno(stderr), .name = "stderr" },
- };
-
- for (i = 0; i < sizeof(files) / sizeof(*files); i++) {
- int out_fd, ret;
-
- ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
- &files[i].name, 1, noop_open, &files[i].fd);
- LTTNG_ASSERT(out_fd == files[i].fd);
-
- ok(ret == 0, "Track unsuspendable fd %d (%s)", files[i].fd,
- files[i].name);
- }
-}
-
-static
-void untrack_std_fds(struct fd_tracker *tracker)
-{
- int i;
- struct { int fd; const char *name; } files[] = {
- { .fd = fileno(stdin), .name = "stdin" },
- { .fd = fileno(stdout), .name = "stdout" },
- { .fd = fileno(stderr), .name = "stderr" },
- };
-
- for (i = 0; i < sizeof(files) / sizeof(*files); i++) {
- int fd = files[i].fd;
- int ret = fd_tracker_close_unsuspendable_fd(tracker,
- &files[i].fd, 1, noop_close, NULL);
-
- ok(ret == 0, "Untrack unsuspendable fd %d (%s)", fd,
- files[i].name);
- }
-}
-
-/*
- * Basic test opening and closing three unsuspendable fds.
- */
-static
-void test_unsuspendable_basic(void)
-{
- int ret;
- struct fd_tracker *tracker;
- char *test_directory = NULL, *unlinked_files_directory = NULL;
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
- ok(tracker, "Created an fd tracker with a limit of %d simulateously opened file descriptors",
- TRACKER_FD_LIMIT);
- if (!tracker) {
- goto end;
- }
-
- track_std_fds(tracker);
- untrack_std_fds(tracker);
-
- fd_tracker_destroy(tracker);
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
-end:
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-static
-int error_open(void *data, int *fds)
-{
- return *((int *) data);
-}
-
-static
-int error_close(void *data, int *fds)
-{
- return *((int *) data);
-}
-
-/*
- * Validate that user callback return values are returned to the
- * caller of the fd tracker.
- */
-static
-void test_unsuspendable_cb_return(void)
-{
- int ret, stdout_fd = fileno(stdout), out_fd = 42;
- struct fd_tracker *tracker;
- int expected_error = -ENETDOWN;
- char *test_directory = NULL, *unlinked_files_directory = NULL;
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- tracker = fd_tracker_create(test_directory, TRACKER_FD_LIMIT);
- LTTNG_ASSERT(tracker);
-
- /* The error_open callback should fail and return 'expected_error'. */
- ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
- NULL, 1, error_open, &expected_error);
- ok(ret == expected_error, "fd_tracker_open_unsuspendable_fd() forwards the user callback's error code");
- ok(out_fd == 42, "Output fd parameter is unaffected on error of fd_tracker_open_unsuspendable_fd()");
-
- /*
- * Track a valid fd since we don't want the tracker to fail with an
- * invalid fd error for this test.
- */
- ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
- NULL, 1, noop_open, &stdout_fd);
- ok(out_fd == stdout_fd, "fd_tracker_open_unsuspendable_fd() sets the output fd parameter to the newly-tracked fd's value");
- LTTNG_ASSERT(!ret);
-
- ret = fd_tracker_close_unsuspendable_fd(tracker,
- &stdout_fd, 1, error_close, &expected_error);
- ok(ret == expected_error, "fd_tracker_close_unsuspendable_fd() forwards the user callback's error code");
- ret = fd_tracker_close_unsuspendable_fd(tracker,
- &stdout_fd, 1, noop_close, &expected_error);
- LTTNG_ASSERT(!ret);
-
- fd_tracker_destroy(tracker);
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-/*
- * Validate that the tracker refuses to track two identical unsuspendable
- * file descriptors.
- */
-static
-void test_unsuspendable_duplicate(void)
-{
- int ret, stdout_fd = fileno(stdout), out_fd;
- struct fd_tracker *tracker;
- char *test_directory = NULL, *unlinked_files_directory = NULL;
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
- LTTNG_ASSERT(tracker);
-
- ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
- NULL, 1, noop_open, &stdout_fd);
- LTTNG_ASSERT(!ret);
- ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
- NULL, 1, noop_open, &stdout_fd);
- ok(ret == -EEXIST, "EEXIST reported on open of an already tracked file descriptor");
-
- ret = fd_tracker_close_unsuspendable_fd(tracker,
- &stdout_fd, 1, noop_close, NULL);
- LTTNG_ASSERT(!ret);
-
- fd_tracker_destroy(tracker);
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-static
-int open_pipes(void *data, int *out_fds)
-{
- unsigned int i;
- const unsigned int pipe_count = TRACKER_FD_LIMIT / 2;
-
- for (i = 0; i < pipe_count; i++) {
- int ret = pipe(&out_fds[i * 2]);
-
- if (ret) {
- return -errno;
- }
- }
- return 0;
-}
-
-static
-int close_pipes(void *data, int *fds)
-{
- int i;
- int *pipes = fds;
-
- for (i = 0; i < TRACKER_FD_LIMIT; i++) {
- int ret = close(pipes[i]);
-
- if (ret) {
- return -errno;
- }
- }
- return 0;
-}
-
-/*
- * Validate that the tracker enforces the open file descriptor limit
- * when unsuspendable file descriptors are being opened.
- */
-static
-void test_unsuspendable_limit(void)
-{
- struct fd_tracker *tracker;
- int ret, stdout_fd = fileno(stdout), out_fd;
- int fds[TRACKER_FD_LIMIT];
- char *test_directory = NULL, *unlinked_files_directory = NULL;
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- /* This test assumes TRACKER_FD_LIMIT is a multiple of 2. */
- LTTNG_ASSERT((TRACKER_FD_LIMIT % 2 == 0) && TRACKER_FD_LIMIT);
-
- tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
- LTTNG_ASSERT(tracker);
-
- ret = fd_tracker_open_unsuspendable_fd(tracker, fds,
- NULL, TRACKER_FD_LIMIT, open_pipes, NULL);
- ok(ret == 0, "File descriptor tracker allowed the user to meet its limit with unsuspendable file descriptors (%d)",
- TRACKER_FD_LIMIT);
-
- ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
- NULL, 1, noop_open, &stdout_fd);
- ok(ret == -EMFILE, "EMFILE reported when exceeding the file descriptor limit while opening an unsuspendable fd");
-
- ret = fd_tracker_close_unsuspendable_fd(tracker,
- fds, TRACKER_FD_LIMIT, close_pipes, NULL);
- LTTNG_ASSERT(!ret);
-
- fd_tracker_destroy(tracker);
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-/*
- * Validate that the tracker refuses to track two identical unsuspendable
- * file descriptors.
- */
-static
-void test_unsuspendable_close_untracked(void)
-{
- int ret, stdout_fd = fileno(stdout), unknown_fds[2], out_fd;
- struct fd_tracker *tracker;
- char *test_directory = NULL, *unlinked_files_directory = NULL;
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
- if (!tracker) {
- goto end;;
- }
-
- ret = pipe(unknown_fds);
- LTTNG_ASSERT(!ret);
- ret = close(unknown_fds[0]);
- LTTNG_ASSERT(ret == 0);
- ret = close(unknown_fds[1]);
- LTTNG_ASSERT(ret == 0);
-
- ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
- NULL, 1, noop_open, &stdout_fd);
- LTTNG_ASSERT(!ret);
-
- ret = fd_tracker_close_unsuspendable_fd(tracker,
- unknown_fds, 1, noop_close, NULL);
- ok(ret == -EINVAL, "EINVAL reported on close of an untracked file descriptor");
-
- ret = fd_tracker_close_unsuspendable_fd(tracker,
- &stdout_fd, 1, noop_close, NULL);
- LTTNG_ASSERT(!ret);
-
- fd_tracker_destroy(tracker);
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
-end:
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-static int open_files(struct fd_tracker *tracker,
- struct lttng_directory_handle *directory,
- unsigned int count,
- struct fs_handle **handles,
- char **file_paths)
-{
- int ret = 0;
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- int p_ret;
- char *file_path;
- struct fs_handle *handle;
- mode_t mode = S_IWUSR | S_IRUSR;
-
- p_ret = asprintf(&file_path, "file-%u", i);
- LTTNG_ASSERT(p_ret >= 0);
- file_paths[i] = file_path;
-
- handle = fd_tracker_open_fs_handle(tracker, directory, file_path,
- O_RDWR | O_CREAT, &mode);
- if (!handle) {
- ret = -1;
- break;
- }
- handles[i] = handle;
- }
- return ret;
-}
-
-static int open_same_file(struct fd_tracker *tracker,
- struct lttng_directory_handle *directory,
- const char *file,
- unsigned int count,
- struct fs_handle **handles)
-{
- int ret = 0;
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- struct fs_handle *handle;
- mode_t mode = S_IWUSR | S_IRUSR;
-
- handle = fd_tracker_open_fs_handle(tracker, directory, file,
- O_RDWR | O_CREAT, &mode);
- if (!handle) {
- ret = -1;
- break;
- }
- handles[i] = handle;
- }
- return ret;
-}
-
-static
-int cleanup_files(struct fd_tracker *tracker, const char *dir,
- unsigned int count, struct fs_handle **handles,
- char **file_paths)
-{
- int ret = 0;
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- char *file_path = file_paths[i];
-
- if (!file_path) {
- break;
- }
- if (fs_handle_unlink(handles[i])) {
- diag("Failed to unlink fs_handle to file %s", file_path);
- ret = -1;
- }
- if (fs_handle_close(handles[i])) {
- diag("Failed to close fs_handle to file %s", file_path);
- ret = -1;
- }
- free(file_path);
- }
- return ret;
-}
-
-static
-void test_suspendable_limit(void)
-{
- int ret;
- const int files_to_create = TRACKER_FD_LIMIT * 10;
- struct fd_tracker *tracker;
- char *test_directory = NULL, *unlinked_files_directory = NULL;
- char *output_files[files_to_create];
- struct fs_handle *handles[files_to_create];
- struct lttng_directory_handle *dir_handle = NULL;
- int dir_handle_fd_count;
-
- memset(output_files, 0, sizeof(output_files));
- memset(handles, 0, sizeof(handles));
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
- if (!tracker) {
- goto end;
- }
-
- dir_handle = lttng_directory_handle_create(test_directory);
- LTTNG_ASSERT(dir_handle);
- dir_handle_fd_count = !!lttng_directory_handle_uses_fd(dir_handle);
-
- ret = open_files(tracker, dir_handle, files_to_create, handles,
- output_files);
- ok(!ret, "Created %d files with a limit of %d simultaneously-opened file descriptor",
- files_to_create, TRACKER_FD_LIMIT);
- check_fd_count(TRACKER_FD_LIMIT + STDIO_FD_COUNT + unknown_fds_count +
- dir_handle_fd_count);
-
- ret = cleanup_files(tracker, test_directory, files_to_create, handles,
- output_files);
- ok(!ret, "Close all opened filesystem handles");
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
- fd_tracker_destroy(tracker);
- lttng_directory_handle_put(dir_handle);
-end:
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-static
-void test_mixed_limit(void)
-{
- int ret;
- const int files_to_create = TRACKER_FD_LIMIT;
- struct fd_tracker *tracker;
- char *test_directory = NULL, *unlinked_files_directory = NULL;
- char *output_files[files_to_create];
- struct fs_handle *handles[files_to_create];
- struct lttng_directory_handle *dir_handle = NULL;
- int dir_handle_fd_count;
-
- memset(output_files, 0, sizeof(output_files));
- memset(handles, 0, sizeof(handles));
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
- if (!tracker) {
- goto end;
- }
-
- dir_handle = lttng_directory_handle_create(test_directory);
- LTTNG_ASSERT(dir_handle);
- dir_handle_fd_count = !!lttng_directory_handle_uses_fd(dir_handle);
-
- ret = open_files(tracker, dir_handle, files_to_create, handles,
- output_files);
- ok(!ret, "Created %d files with a limit of %d simultaneously-opened file descriptor",
- files_to_create, TRACKER_FD_LIMIT);
- diag("Check file descriptor count after opening %u files", files_to_create);
- check_fd_count(TRACKER_FD_LIMIT + STDIO_FD_COUNT + unknown_fds_count +
- dir_handle_fd_count);
-
- /*
- * Open unsuspendable fds (stdin, stdout, stderr) and verify that the fd
- * cap is still respected.
- */
- diag("Check file descriptor count after adding %d unsuspendable fds",
- STDIO_FD_COUNT);
- track_std_fds(tracker);
- check_fd_count(TRACKER_FD_LIMIT + unknown_fds_count +
- dir_handle_fd_count);
- diag("Untrack unsuspendable file descriptors");
- untrack_std_fds(tracker);
- check_fd_count(TRACKER_FD_LIMIT + unknown_fds_count +
- dir_handle_fd_count);
-
- ret = cleanup_files(tracker, test_directory, files_to_create, handles,
- output_files);
- ok(!ret, "Close all opened filesystem handles");
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
- fd_tracker_destroy(tracker);
- lttng_directory_handle_put(dir_handle);
-end:
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-/*
- * Open more files than allowed by the fd tracker's cap and write,
- * byte-by-byte, and in round-robin, a string. The goal is to force
- * the fd tracker to suspend and resume the fs_handles often and
- * verify that the fd cap is always respected.
- *
- * The content of the files is also verified at the end.
- */
-static
-void test_suspendable_restore(void)
-{
- int ret;
- const int files_to_create = TRACKER_FD_LIMIT * 10;
- struct fd_tracker *tracker;
- char *output_files[files_to_create];
- struct fs_handle *handles[files_to_create];
- size_t content_index;
- int handle_index;
- bool write_success = true;
- bool fd_cap_respected = true;
- bool content_ok = true;
- struct lttng_directory_handle *dir_handle = NULL;
- int dir_handle_fd_count;
- char *test_directory = NULL, *unlinked_files_directory = NULL;
-
- memset(output_files, 0, sizeof(output_files));
- memset(handles, 0, sizeof(handles));
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
-
- tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
- if (!tracker) {
- goto end;
- }
-
- dir_handle = lttng_directory_handle_create(test_directory);
- LTTNG_ASSERT(dir_handle);
- dir_handle_fd_count = !!lttng_directory_handle_uses_fd(dir_handle);
-
- ret = open_files(tracker, dir_handle, files_to_create, handles,
- output_files);
- ok(!ret, "Created %d files with a limit of %d simultaneously-opened file descriptor",
- files_to_create, TRACKER_FD_LIMIT);
- diag("Check file descriptor count after opening %u files", files_to_create);
- check_fd_count(TRACKER_FD_LIMIT + STDIO_FD_COUNT + unknown_fds_count +
- dir_handle_fd_count);
-
- for (content_index = 0; content_index < sizeof(file_contents); content_index++) {
- for (handle_index = 0; handle_index < files_to_create; handle_index++) {
- int fd;
- struct fs_handle *handle = handles[handle_index];
- const char *path = output_files[handle_index];
-
- fd = fs_handle_get_fd(handle);
- if (fd < 0) {
- write_success = false;
- diag("Failed to restore fs_handle to %s",
- path);
- goto skip_write;
- }
-
- do {
- ret = write(fd, file_contents + content_index, 1);
- } while (ret < 0 && errno == EINTR);
-
- if (ret != 1) {
- write_success = false;
- PERROR("write() to %s failed", path);
- goto skip_write;
- }
-
- if (fd_count() > (TRACKER_FD_LIMIT + STDIO_FD_COUNT +
- unknown_fds_count +
- dir_handle_fd_count)) {
- fd_cap_respected = false;
- }
-
- fs_handle_put_fd(handle);
- }
- }
-skip_write:
- ok(write_success, "Wrote reference string to %d files",
- files_to_create);
- ok(fd_cap_respected, "FD tracker enforced the file descriptor cap");
-
- /* Validate the contents of the files. */
- for (handle_index = 0; handle_index < files_to_create; handle_index++) {
- struct stat fd_stat;
- const char *path = output_files[handle_index];
- char read_buf[sizeof(file_contents)];
- char *read_pos;
- size_t to_read = sizeof(read_buf);
- int fd;
-
- fd = lttng_directory_handle_open_file(
- dir_handle, path, O_RDONLY, 0);
- LTTNG_ASSERT(fd >= 0);
- ret = fstat(fd, &fd_stat);
- LTTNG_ASSERT(!ret);
- if (fd_stat.st_size != sizeof(file_contents)) {
- diag("Content size of file %s doesn't match, got %" PRId64 ", expected %zu",
- path, (int64_t) fd_stat.st_size,
- sizeof(file_contents));
- content_ok = false;
- (void) close(fd);
- break;
- }
-
- read_pos = read_buf;
- do {
- ret = read(fd, read_pos, to_read);
- if (ret > 0) {
- to_read -= ret;
- read_pos += ret;
- }
- } while (to_read && (ret < 0 && errno == EINTR));
- if (ret < 0) {
- content_ok = false;
- PERROR("Failed to read file %s", path);
- (void) close(fd);
- break;
- }
-
- if (strcmp(file_contents, read_buf)) {
- content_ok = false;
- diag("File content doesn't match the expectated string");
- (void) close(fd);
- break;
- }
- (void) close(fd);
- }
- ok(content_ok, "Files contain the expected content");
- ret = cleanup_files(tracker, test_directory, files_to_create, handles,
- output_files);
- ok(!ret, "Close all opened filesystem handles");
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
- fd_tracker_destroy(tracker);
- lttng_directory_handle_put(dir_handle);
-end:
- free(test_directory);
- free(unlinked_files_directory);
-}
-
-static
-void test_unlink(void)
-{
- int ret;
- struct fd_tracker *tracker;
- const int handles_to_open = 2;
- struct fs_handle *handles[handles_to_open];
- struct fs_handle *new_handle = NULL;
- struct stat statbuf;
- struct lttng_directory_handle *dir_handle = NULL;
- const char file_name[] = "my_file";
- char *test_directory = NULL, *unlinked_files_directory = NULL;
- char *unlinked_file_zero = NULL, *unlinked_file_one = NULL;
- int fd;
-
- get_temporary_directories(&test_directory, &unlinked_files_directory);
- ret = asprintf(&unlinked_file_zero, "%s/%u", unlinked_files_directory,
- 0);
- LTTNG_ASSERT(ret > 0);
- ret = asprintf(&unlinked_file_one, "%s/%u", unlinked_files_directory,
- 1);
- LTTNG_ASSERT(ret > 0);
-
- tracker = fd_tracker_create(unlinked_files_directory, 1);
- if (!tracker) {
- goto end;
- }
-
- dir_handle = lttng_directory_handle_create(test_directory);
- LTTNG_ASSERT(dir_handle);
-
- /* Open two handles to the same file. */
- ret = open_same_file(tracker, dir_handle, file_name, handles_to_open,
- handles);
- ok(!ret, "Successfully opened %i handles to %s/%s", handles_to_open,
- test_directory, file_name);
- if (ret) {
- goto end;
- }
-
- /*
- * Unlinking the first handle should cause the file to be renamed
- * to '0'.
- */
- ret = fs_handle_unlink(handles[0]);
- ok(!ret, "Successfully unlinked the first handle to %s/%s",
- test_directory, file_name);
-
- /*
- * The original file should no longer exist on the file system, and a
- * new file named '0' should exist.
- */
- ok(lttng_directory_handle_stat(dir_handle, file_name, &statbuf) == -1 &&
- errno == ENOENT,
- "%s no longer present on file system after unlink",
- file_name);
- ok(lttng_directory_handle_stat(
- dir_handle, unlinked_file_zero, &statbuf) == 0,
- "%s exists on file system after unlink",
- unlinked_file_zero);
-
- /*
- * It should be possible to use the file descriptors of both handles.
- * Since only one file descriptor can be opened at once, this should
- * force the fd_tracker to suspend and restore the handles.
- */
- fd = fs_handle_get_fd(handles[0]);
- ok(fd >= 0, "Got fd from first handle");
-
- fd = fs_handle_get_fd(handles[1]);
- ok (fd < 0, "fd tracker does not allow two fds to be used at once");
-
- fs_handle_put_fd(handles[0]);
- fd = fs_handle_get_fd(handles[1]);
- ok(fd >= 0, "Got fd from second handle");
- fs_handle_put_fd(handles[1]);
-
- /* The second unlink should fail with -ENOENT. */
- ret = fs_handle_unlink(handles[1]);
- ok(ret == -ENOENT,
- "ENOENT is reported when attempting to unlink the second handle to %s/%s",
- test_directory, file_name);
-
- /*
- * Opening a new handle to 'my_file' should succeed.
- */
- ret = open_same_file(tracker, dir_handle, file_name, 1, &new_handle);
- ok(!ret, "Successfully opened a new handle to previously unlinked file %s/%s",
- test_directory, file_name);
- LTTNG_ASSERT(new_handle);
-
- /*
- * Unlinking the new handle should cause the file to be renamed
- * to '1' since '0' already exists.
- */
- ret = fs_handle_unlink(new_handle);
- ok(!ret, "Successfully unlinked the new handle handle to %s/%s",
- test_directory, file_name);
- ok(stat(unlinked_file_one, &statbuf) == 0,
- "%s exists on file system after unlink",
- unlinked_file_one);
-
- ret = fs_handle_close(handles[0]);
- ok(!ret, "Successfully closed the first handle");
- ret = fs_handle_close(handles[1]);
- ok(!ret, "Successfully closed the second handle");
- ret = fs_handle_close(new_handle);
- ok(!ret, "Successfully closed the third handle");
-
- ok(lttng_directory_handle_stat(dir_handle, file_name, &statbuf) == -1 &&
- errno == ENOENT,
- "%s no longer present on file system after handle close",
- file_name);
- ok(lttng_directory_handle_stat(
- dir_handle, unlinked_file_zero, &statbuf) == -1 &&
- errno == ENOENT,
- "%s no longer present on file system after handle close",
- unlinked_file_zero);
- ok(lttng_directory_handle_stat(dir_handle, unlinked_file_one,
- &statbuf) == -1 &&
- errno == ENOENT,
- "%s no longer present on file system after handle close",
- unlinked_file_one);
-
- ret = rmdir(test_directory);
- ok(ret == 0, "Test directory is empty");
-end:
- fd_tracker_destroy(tracker);
- free(test_directory);
- free(unlinked_files_directory);
- free(unlinked_file_zero);
- free(unlinked_file_one);
- lttng_directory_handle_put(dir_handle);
-}
-
-int main(int argc, char **argv)
-{
- plan_tests(NUM_TESTS);
- diag("File descriptor tracker unit tests");
-
- rcu_register_thread();
-
- unknown_fds_count = fd_count() - STDIO_FD_COUNT;
- LTTNG_ASSERT(unknown_fds_count >= 0);
-
- diag("Unsuspendable - basic");
- test_unsuspendable_basic();
- diag("Unsuspendable - callback return values");
- test_unsuspendable_cb_return();
- diag("Unsuspendable - duplicate file descriptors");
- test_unsuspendable_duplicate();
- diag("Unsuspendable - closing an untracked file descriptor");
- test_unsuspendable_close_untracked();
- diag("Unsuspendable - check that file descriptor limit is enforced");
- test_unsuspendable_limit();
-
- diag("Suspendable - check that file descriptor limit is enforced");
- test_suspendable_limit();
- diag("Suspendable - restoration test");
- test_suspendable_restore();
-
- diag("Mixed - check that file descriptor limit is enforced");
- test_mixed_limit();
-
- diag("Suspendable - Unlinking test");
- test_unlink();
-
- rcu_barrier();
- rcu_unregister_thread();
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdarg.h>
+#include <tap/tap.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <urcu.h>
+
+#include <common/compat/directory-handle.h>
+#include <common/compat/errno.h>
+#include <common/error.h>
+#include <common/fs-handle.h>
+#include <common/fd-tracker/fd-tracker.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+/* Number of TAP tests in this file */
+#define NUM_TESTS 61
+/* 3 for stdin, stdout, and stderr */
+#define STDIO_FD_COUNT 3
+#define TRACKER_FD_LIMIT 50
+#define TMP_DIR_PATTERN "/tmp/fd-tracker-XXXXXX"
+#define TEST_UNLINK_DIRECTORY_NAME "unlinked_files"
+
+#ifdef __linux__
+#define SELF_FD_DIR "/proc/self/fd"
+#else
+/* Most Unices have /dev/fd */
+#define SELF_FD_DIR "/dev/fd"
+#endif
+
+/*
+ * Count of fds, beyond stdin, stderr, stdout that were open
+ * at the launch of the test. This allows the test to succeed when
+ * run by automake's test runner or valgrind which both open
+ * fds behind our back.
+ */
+int unknown_fds_count;
+
+const char file_contents[] = "Bacon ipsum dolor amet jerky drumstick sirloin "
+ "strip steak venison boudin filet mignon picanha doner shoulder. "
+ "Strip steak brisket alcatra, venison beef chuck cupim pastrami. "
+ "Landjaeger tri-tip salami leberkas ball tip, ham hock chuck sausage "
+ "flank jerky cupim. Pig bacon chuck pancetta andouille.";
+
+static
+void get_temporary_directories(char **_test_directory, char **_unlink_directory)
+{
+ int ret;
+ char tmp_path_pattern[] = TMP_DIR_PATTERN;
+ char *output_dir;
+
+ output_dir = mkdtemp(tmp_path_pattern);
+ if (!output_dir) {
+ diag("Failed to create temporary path of the form %s",
+ TMP_DIR_PATTERN);
+ abort();
+ }
+
+ *_test_directory = strdup(output_dir);
+ LTTNG_ASSERT(*_test_directory);
+ ret = asprintf(_unlink_directory, "%s/%s", output_dir,
+ TEST_UNLINK_DIRECTORY_NAME);
+ if (ret < 0) {
+ abort();
+ }
+}
+
+static
+int fd_count(void)
+{
+ DIR *dir;
+ struct dirent *entry;
+ int count = 0;
+
+ dir = opendir(SELF_FD_DIR);
+ if (!dir) {
+ perror("# Failed to enumerate " SELF_FD_DIR " to count the number of used file descriptors");
+ count = -1;
+ goto end;
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
+ continue;
+ }
+ count++;
+ }
+ /* Don't account for the file descriptor opened by opendir(). */
+ count--;
+ if (closedir(dir)) {
+ perror("# Failed to close test program's " SELF_FD_DIR " directory file descriptor");
+ }
+end:
+ return count;
+}
+
+static
+void check_fd_count(int expected_count)
+{
+ int count = 0;
+
+ count = fd_count();
+ ok(count == expected_count, "Expected %d open file descriptors (%d are open)",
+ expected_count, count);
+}
+
+static
+int noop_open(void *data, int *fds)
+{
+ *fds = *((int *) data);
+ return 0;
+}
+
+static
+int noop_close(void *data, int *fds)
+{
+ return 0;
+}
+
+static
+void track_std_fds(struct fd_tracker *tracker)
+{
+ int i;
+ struct { int fd; const char *name; } files[] = {
+ { .fd = fileno(stdin), .name = "stdin" },
+ { .fd = fileno(stdout), .name = "stdout" },
+ { .fd = fileno(stderr), .name = "stderr" },
+ };
+
+ for (i = 0; i < sizeof(files) / sizeof(*files); i++) {
+ int out_fd, ret;
+
+ ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
+ &files[i].name, 1, noop_open, &files[i].fd);
+ LTTNG_ASSERT(out_fd == files[i].fd);
+
+ ok(ret == 0, "Track unsuspendable fd %d (%s)", files[i].fd,
+ files[i].name);
+ }
+}
+
+static
+void untrack_std_fds(struct fd_tracker *tracker)
+{
+ int i;
+ struct { int fd; const char *name; } files[] = {
+ { .fd = fileno(stdin), .name = "stdin" },
+ { .fd = fileno(stdout), .name = "stdout" },
+ { .fd = fileno(stderr), .name = "stderr" },
+ };
+
+ for (i = 0; i < sizeof(files) / sizeof(*files); i++) {
+ int fd = files[i].fd;
+ int ret = fd_tracker_close_unsuspendable_fd(tracker,
+ &files[i].fd, 1, noop_close, NULL);
+
+ ok(ret == 0, "Untrack unsuspendable fd %d (%s)", fd,
+ files[i].name);
+ }
+}
+
+/*
+ * Basic test opening and closing three unsuspendable fds.
+ */
+static
+void test_unsuspendable_basic(void)
+{
+ int ret;
+ struct fd_tracker *tracker;
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
+ ok(tracker, "Created an fd tracker with a limit of %d simulateously opened file descriptors",
+ TRACKER_FD_LIMIT);
+ if (!tracker) {
+ goto end;
+ }
+
+ track_std_fds(tracker);
+ untrack_std_fds(tracker);
+
+ fd_tracker_destroy(tracker);
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+end:
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+static
+int error_open(void *data, int *fds)
+{
+ return *((int *) data);
+}
+
+static
+int error_close(void *data, int *fds)
+{
+ return *((int *) data);
+}
+
+/*
+ * Validate that user callback return values are returned to the
+ * caller of the fd tracker.
+ */
+static
+void test_unsuspendable_cb_return(void)
+{
+ int ret, stdout_fd = fileno(stdout), out_fd = 42;
+ struct fd_tracker *tracker;
+ int expected_error = -ENETDOWN;
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ tracker = fd_tracker_create(test_directory, TRACKER_FD_LIMIT);
+ LTTNG_ASSERT(tracker);
+
+ /* The error_open callback should fail and return 'expected_error'. */
+ ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
+ NULL, 1, error_open, &expected_error);
+ ok(ret == expected_error, "fd_tracker_open_unsuspendable_fd() forwards the user callback's error code");
+ ok(out_fd == 42, "Output fd parameter is unaffected on error of fd_tracker_open_unsuspendable_fd()");
+
+ /*
+ * Track a valid fd since we don't want the tracker to fail with an
+ * invalid fd error for this test.
+ */
+ ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
+ NULL, 1, noop_open, &stdout_fd);
+ ok(out_fd == stdout_fd, "fd_tracker_open_unsuspendable_fd() sets the output fd parameter to the newly-tracked fd's value");
+ LTTNG_ASSERT(!ret);
+
+ ret = fd_tracker_close_unsuspendable_fd(tracker,
+ &stdout_fd, 1, error_close, &expected_error);
+ ok(ret == expected_error, "fd_tracker_close_unsuspendable_fd() forwards the user callback's error code");
+ ret = fd_tracker_close_unsuspendable_fd(tracker,
+ &stdout_fd, 1, noop_close, &expected_error);
+ LTTNG_ASSERT(!ret);
+
+ fd_tracker_destroy(tracker);
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+/*
+ * Validate that the tracker refuses to track two identical unsuspendable
+ * file descriptors.
+ */
+static
+void test_unsuspendable_duplicate(void)
+{
+ int ret, stdout_fd = fileno(stdout), out_fd;
+ struct fd_tracker *tracker;
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
+ LTTNG_ASSERT(tracker);
+
+ ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
+ NULL, 1, noop_open, &stdout_fd);
+ LTTNG_ASSERT(!ret);
+ ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
+ NULL, 1, noop_open, &stdout_fd);
+ ok(ret == -EEXIST, "EEXIST reported on open of an already tracked file descriptor");
+
+ ret = fd_tracker_close_unsuspendable_fd(tracker,
+ &stdout_fd, 1, noop_close, NULL);
+ LTTNG_ASSERT(!ret);
+
+ fd_tracker_destroy(tracker);
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+static
+int open_pipes(void *data, int *out_fds)
+{
+ unsigned int i;
+ const unsigned int pipe_count = TRACKER_FD_LIMIT / 2;
+
+ for (i = 0; i < pipe_count; i++) {
+ int ret = pipe(&out_fds[i * 2]);
+
+ if (ret) {
+ return -errno;
+ }
+ }
+ return 0;
+}
+
+static
+int close_pipes(void *data, int *fds)
+{
+ int i;
+ int *pipes = fds;
+
+ for (i = 0; i < TRACKER_FD_LIMIT; i++) {
+ int ret = close(pipes[i]);
+
+ if (ret) {
+ return -errno;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Validate that the tracker enforces the open file descriptor limit
+ * when unsuspendable file descriptors are being opened.
+ */
+static
+void test_unsuspendable_limit(void)
+{
+ struct fd_tracker *tracker;
+ int ret, stdout_fd = fileno(stdout), out_fd;
+ int fds[TRACKER_FD_LIMIT];
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ /* This test assumes TRACKER_FD_LIMIT is a multiple of 2. */
+ LTTNG_ASSERT((TRACKER_FD_LIMIT % 2 == 0) && TRACKER_FD_LIMIT);
+
+ tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
+ LTTNG_ASSERT(tracker);
+
+ ret = fd_tracker_open_unsuspendable_fd(tracker, fds,
+ NULL, TRACKER_FD_LIMIT, open_pipes, NULL);
+ ok(ret == 0, "File descriptor tracker allowed the user to meet its limit with unsuspendable file descriptors (%d)",
+ TRACKER_FD_LIMIT);
+
+ ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
+ NULL, 1, noop_open, &stdout_fd);
+ ok(ret == -EMFILE, "EMFILE reported when exceeding the file descriptor limit while opening an unsuspendable fd");
+
+ ret = fd_tracker_close_unsuspendable_fd(tracker,
+ fds, TRACKER_FD_LIMIT, close_pipes, NULL);
+ LTTNG_ASSERT(!ret);
+
+ fd_tracker_destroy(tracker);
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+/*
+ * Validate that the tracker refuses to track two identical unsuspendable
+ * file descriptors.
+ */
+static
+void test_unsuspendable_close_untracked(void)
+{
+ int ret, stdout_fd = fileno(stdout), unknown_fds[2], out_fd;
+ struct fd_tracker *tracker;
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
+ if (!tracker) {
+ goto end;;
+ }
+
+ ret = pipe(unknown_fds);
+ LTTNG_ASSERT(!ret);
+ ret = close(unknown_fds[0]);
+ LTTNG_ASSERT(ret == 0);
+ ret = close(unknown_fds[1]);
+ LTTNG_ASSERT(ret == 0);
+
+ ret = fd_tracker_open_unsuspendable_fd(tracker, &out_fd,
+ NULL, 1, noop_open, &stdout_fd);
+ LTTNG_ASSERT(!ret);
+
+ ret = fd_tracker_close_unsuspendable_fd(tracker,
+ unknown_fds, 1, noop_close, NULL);
+ ok(ret == -EINVAL, "EINVAL reported on close of an untracked file descriptor");
+
+ ret = fd_tracker_close_unsuspendable_fd(tracker,
+ &stdout_fd, 1, noop_close, NULL);
+ LTTNG_ASSERT(!ret);
+
+ fd_tracker_destroy(tracker);
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+end:
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+static int open_files(struct fd_tracker *tracker,
+ struct lttng_directory_handle *directory,
+ unsigned int count,
+ struct fs_handle **handles,
+ char **file_paths)
+{
+ int ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ int p_ret;
+ char *file_path;
+ struct fs_handle *handle;
+ mode_t mode = S_IWUSR | S_IRUSR;
+
+ p_ret = asprintf(&file_path, "file-%u", i);
+ LTTNG_ASSERT(p_ret >= 0);
+ file_paths[i] = file_path;
+
+ handle = fd_tracker_open_fs_handle(tracker, directory, file_path,
+ O_RDWR | O_CREAT, &mode);
+ if (!handle) {
+ ret = -1;
+ break;
+ }
+ handles[i] = handle;
+ }
+ return ret;
+}
+
+static int open_same_file(struct fd_tracker *tracker,
+ struct lttng_directory_handle *directory,
+ const char *file,
+ unsigned int count,
+ struct fs_handle **handles)
+{
+ int ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ struct fs_handle *handle;
+ mode_t mode = S_IWUSR | S_IRUSR;
+
+ handle = fd_tracker_open_fs_handle(tracker, directory, file,
+ O_RDWR | O_CREAT, &mode);
+ if (!handle) {
+ ret = -1;
+ break;
+ }
+ handles[i] = handle;
+ }
+ return ret;
+}
+
+static
+int cleanup_files(struct fd_tracker *tracker, const char *dir,
+ unsigned int count, struct fs_handle **handles,
+ char **file_paths)
+{
+ int ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ char *file_path = file_paths[i];
+
+ if (!file_path) {
+ break;
+ }
+ if (fs_handle_unlink(handles[i])) {
+ diag("Failed to unlink fs_handle to file %s", file_path);
+ ret = -1;
+ }
+ if (fs_handle_close(handles[i])) {
+ diag("Failed to close fs_handle to file %s", file_path);
+ ret = -1;
+ }
+ free(file_path);
+ }
+ return ret;
+}
+
+static
+void test_suspendable_limit(void)
+{
+ int ret;
+ const int files_to_create = TRACKER_FD_LIMIT * 10;
+ struct fd_tracker *tracker;
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+ char *output_files[files_to_create];
+ struct fs_handle *handles[files_to_create];
+ struct lttng_directory_handle *dir_handle = NULL;
+ int dir_handle_fd_count;
+
+ memset(output_files, 0, sizeof(output_files));
+ memset(handles, 0, sizeof(handles));
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
+ if (!tracker) {
+ goto end;
+ }
+
+ dir_handle = lttng_directory_handle_create(test_directory);
+ LTTNG_ASSERT(dir_handle);
+ dir_handle_fd_count = !!lttng_directory_handle_uses_fd(dir_handle);
+
+ ret = open_files(tracker, dir_handle, files_to_create, handles,
+ output_files);
+ ok(!ret, "Created %d files with a limit of %d simultaneously-opened file descriptor",
+ files_to_create, TRACKER_FD_LIMIT);
+ check_fd_count(TRACKER_FD_LIMIT + STDIO_FD_COUNT + unknown_fds_count +
+ dir_handle_fd_count);
+
+ ret = cleanup_files(tracker, test_directory, files_to_create, handles,
+ output_files);
+ ok(!ret, "Close all opened filesystem handles");
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+ fd_tracker_destroy(tracker);
+ lttng_directory_handle_put(dir_handle);
+end:
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+static
+void test_mixed_limit(void)
+{
+ int ret;
+ const int files_to_create = TRACKER_FD_LIMIT;
+ struct fd_tracker *tracker;
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+ char *output_files[files_to_create];
+ struct fs_handle *handles[files_to_create];
+ struct lttng_directory_handle *dir_handle = NULL;
+ int dir_handle_fd_count;
+
+ memset(output_files, 0, sizeof(output_files));
+ memset(handles, 0, sizeof(handles));
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
+ if (!tracker) {
+ goto end;
+ }
+
+ dir_handle = lttng_directory_handle_create(test_directory);
+ LTTNG_ASSERT(dir_handle);
+ dir_handle_fd_count = !!lttng_directory_handle_uses_fd(dir_handle);
+
+ ret = open_files(tracker, dir_handle, files_to_create, handles,
+ output_files);
+ ok(!ret, "Created %d files with a limit of %d simultaneously-opened file descriptor",
+ files_to_create, TRACKER_FD_LIMIT);
+ diag("Check file descriptor count after opening %u files", files_to_create);
+ check_fd_count(TRACKER_FD_LIMIT + STDIO_FD_COUNT + unknown_fds_count +
+ dir_handle_fd_count);
+
+ /*
+ * Open unsuspendable fds (stdin, stdout, stderr) and verify that the fd
+ * cap is still respected.
+ */
+ diag("Check file descriptor count after adding %d unsuspendable fds",
+ STDIO_FD_COUNT);
+ track_std_fds(tracker);
+ check_fd_count(TRACKER_FD_LIMIT + unknown_fds_count +
+ dir_handle_fd_count);
+ diag("Untrack unsuspendable file descriptors");
+ untrack_std_fds(tracker);
+ check_fd_count(TRACKER_FD_LIMIT + unknown_fds_count +
+ dir_handle_fd_count);
+
+ ret = cleanup_files(tracker, test_directory, files_to_create, handles,
+ output_files);
+ ok(!ret, "Close all opened filesystem handles");
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+ fd_tracker_destroy(tracker);
+ lttng_directory_handle_put(dir_handle);
+end:
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+/*
+ * Open more files than allowed by the fd tracker's cap and write,
+ * byte-by-byte, and in round-robin, a string. The goal is to force
+ * the fd tracker to suspend and resume the fs_handles often and
+ * verify that the fd cap is always respected.
+ *
+ * The content of the files is also verified at the end.
+ */
+static
+void test_suspendable_restore(void)
+{
+ int ret;
+ const int files_to_create = TRACKER_FD_LIMIT * 10;
+ struct fd_tracker *tracker;
+ char *output_files[files_to_create];
+ struct fs_handle *handles[files_to_create];
+ size_t content_index;
+ int handle_index;
+ bool write_success = true;
+ bool fd_cap_respected = true;
+ bool content_ok = true;
+ struct lttng_directory_handle *dir_handle = NULL;
+ int dir_handle_fd_count;
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+
+ memset(output_files, 0, sizeof(output_files));
+ memset(handles, 0, sizeof(handles));
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+
+ tracker = fd_tracker_create(unlinked_files_directory, TRACKER_FD_LIMIT);
+ if (!tracker) {
+ goto end;
+ }
+
+ dir_handle = lttng_directory_handle_create(test_directory);
+ LTTNG_ASSERT(dir_handle);
+ dir_handle_fd_count = !!lttng_directory_handle_uses_fd(dir_handle);
+
+ ret = open_files(tracker, dir_handle, files_to_create, handles,
+ output_files);
+ ok(!ret, "Created %d files with a limit of %d simultaneously-opened file descriptor",
+ files_to_create, TRACKER_FD_LIMIT);
+ diag("Check file descriptor count after opening %u files", files_to_create);
+ check_fd_count(TRACKER_FD_LIMIT + STDIO_FD_COUNT + unknown_fds_count +
+ dir_handle_fd_count);
+
+ for (content_index = 0; content_index < sizeof(file_contents); content_index++) {
+ for (handle_index = 0; handle_index < files_to_create; handle_index++) {
+ int fd;
+ struct fs_handle *handle = handles[handle_index];
+ const char *path = output_files[handle_index];
+
+ fd = fs_handle_get_fd(handle);
+ if (fd < 0) {
+ write_success = false;
+ diag("Failed to restore fs_handle to %s",
+ path);
+ goto skip_write;
+ }
+
+ do {
+ ret = write(fd, file_contents + content_index, 1);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret != 1) {
+ write_success = false;
+ PERROR("write() to %s failed", path);
+ goto skip_write;
+ }
+
+ if (fd_count() > (TRACKER_FD_LIMIT + STDIO_FD_COUNT +
+ unknown_fds_count +
+ dir_handle_fd_count)) {
+ fd_cap_respected = false;
+ }
+
+ fs_handle_put_fd(handle);
+ }
+ }
+skip_write:
+ ok(write_success, "Wrote reference string to %d files",
+ files_to_create);
+ ok(fd_cap_respected, "FD tracker enforced the file descriptor cap");
+
+ /* Validate the contents of the files. */
+ for (handle_index = 0; handle_index < files_to_create; handle_index++) {
+ struct stat fd_stat;
+ const char *path = output_files[handle_index];
+ char read_buf[sizeof(file_contents)];
+ char *read_pos;
+ size_t to_read = sizeof(read_buf);
+ int fd;
+
+ fd = lttng_directory_handle_open_file(
+ dir_handle, path, O_RDONLY, 0);
+ LTTNG_ASSERT(fd >= 0);
+ ret = fstat(fd, &fd_stat);
+ LTTNG_ASSERT(!ret);
+ if (fd_stat.st_size != sizeof(file_contents)) {
+ diag("Content size of file %s doesn't match, got %" PRId64 ", expected %zu",
+ path, (int64_t) fd_stat.st_size,
+ sizeof(file_contents));
+ content_ok = false;
+ (void) close(fd);
+ break;
+ }
+
+ read_pos = read_buf;
+ do {
+ ret = read(fd, read_pos, to_read);
+ if (ret > 0) {
+ to_read -= ret;
+ read_pos += ret;
+ }
+ } while (to_read && (ret < 0 && errno == EINTR));
+ if (ret < 0) {
+ content_ok = false;
+ PERROR("Failed to read file %s", path);
+ (void) close(fd);
+ break;
+ }
+
+ if (strcmp(file_contents, read_buf)) {
+ content_ok = false;
+ diag("File content doesn't match the expectated string");
+ (void) close(fd);
+ break;
+ }
+ (void) close(fd);
+ }
+ ok(content_ok, "Files contain the expected content");
+ ret = cleanup_files(tracker, test_directory, files_to_create, handles,
+ output_files);
+ ok(!ret, "Close all opened filesystem handles");
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+ fd_tracker_destroy(tracker);
+ lttng_directory_handle_put(dir_handle);
+end:
+ free(test_directory);
+ free(unlinked_files_directory);
+}
+
+static
+void test_unlink(void)
+{
+ int ret;
+ struct fd_tracker *tracker;
+ const int handles_to_open = 2;
+ struct fs_handle *handles[handles_to_open];
+ struct fs_handle *new_handle = NULL;
+ struct stat statbuf;
+ struct lttng_directory_handle *dir_handle = NULL;
+ const char file_name[] = "my_file";
+ char *test_directory = NULL, *unlinked_files_directory = NULL;
+ char *unlinked_file_zero = NULL, *unlinked_file_one = NULL;
+ int fd;
+
+ get_temporary_directories(&test_directory, &unlinked_files_directory);
+ ret = asprintf(&unlinked_file_zero, "%s/%u", unlinked_files_directory,
+ 0);
+ LTTNG_ASSERT(ret > 0);
+ ret = asprintf(&unlinked_file_one, "%s/%u", unlinked_files_directory,
+ 1);
+ LTTNG_ASSERT(ret > 0);
+
+ tracker = fd_tracker_create(unlinked_files_directory, 1);
+ if (!tracker) {
+ goto end;
+ }
+
+ dir_handle = lttng_directory_handle_create(test_directory);
+ LTTNG_ASSERT(dir_handle);
+
+ /* Open two handles to the same file. */
+ ret = open_same_file(tracker, dir_handle, file_name, handles_to_open,
+ handles);
+ ok(!ret, "Successfully opened %i handles to %s/%s", handles_to_open,
+ test_directory, file_name);
+ if (ret) {
+ goto end;
+ }
+
+ /*
+ * Unlinking the first handle should cause the file to be renamed
+ * to '0'.
+ */
+ ret = fs_handle_unlink(handles[0]);
+ ok(!ret, "Successfully unlinked the first handle to %s/%s",
+ test_directory, file_name);
+
+ /*
+ * The original file should no longer exist on the file system, and a
+ * new file named '0' should exist.
+ */
+ ok(lttng_directory_handle_stat(dir_handle, file_name, &statbuf) == -1 &&
+ errno == ENOENT,
+ "%s no longer present on file system after unlink",
+ file_name);
+ ok(lttng_directory_handle_stat(
+ dir_handle, unlinked_file_zero, &statbuf) == 0,
+ "%s exists on file system after unlink",
+ unlinked_file_zero);
+
+ /*
+ * It should be possible to use the file descriptors of both handles.
+ * Since only one file descriptor can be opened at once, this should
+ * force the fd_tracker to suspend and restore the handles.
+ */
+ fd = fs_handle_get_fd(handles[0]);
+ ok(fd >= 0, "Got fd from first handle");
+
+ fd = fs_handle_get_fd(handles[1]);
+ ok (fd < 0, "fd tracker does not allow two fds to be used at once");
+
+ fs_handle_put_fd(handles[0]);
+ fd = fs_handle_get_fd(handles[1]);
+ ok(fd >= 0, "Got fd from second handle");
+ fs_handle_put_fd(handles[1]);
+
+ /* The second unlink should fail with -ENOENT. */
+ ret = fs_handle_unlink(handles[1]);
+ ok(ret == -ENOENT,
+ "ENOENT is reported when attempting to unlink the second handle to %s/%s",
+ test_directory, file_name);
+
+ /*
+ * Opening a new handle to 'my_file' should succeed.
+ */
+ ret = open_same_file(tracker, dir_handle, file_name, 1, &new_handle);
+ ok(!ret, "Successfully opened a new handle to previously unlinked file %s/%s",
+ test_directory, file_name);
+ LTTNG_ASSERT(new_handle);
+
+ /*
+ * Unlinking the new handle should cause the file to be renamed
+ * to '1' since '0' already exists.
+ */
+ ret = fs_handle_unlink(new_handle);
+ ok(!ret, "Successfully unlinked the new handle handle to %s/%s",
+ test_directory, file_name);
+ ok(stat(unlinked_file_one, &statbuf) == 0,
+ "%s exists on file system after unlink",
+ unlinked_file_one);
+
+ ret = fs_handle_close(handles[0]);
+ ok(!ret, "Successfully closed the first handle");
+ ret = fs_handle_close(handles[1]);
+ ok(!ret, "Successfully closed the second handle");
+ ret = fs_handle_close(new_handle);
+ ok(!ret, "Successfully closed the third handle");
+
+ ok(lttng_directory_handle_stat(dir_handle, file_name, &statbuf) == -1 &&
+ errno == ENOENT,
+ "%s no longer present on file system after handle close",
+ file_name);
+ ok(lttng_directory_handle_stat(
+ dir_handle, unlinked_file_zero, &statbuf) == -1 &&
+ errno == ENOENT,
+ "%s no longer present on file system after handle close",
+ unlinked_file_zero);
+ ok(lttng_directory_handle_stat(dir_handle, unlinked_file_one,
+ &statbuf) == -1 &&
+ errno == ENOENT,
+ "%s no longer present on file system after handle close",
+ unlinked_file_one);
+
+ ret = rmdir(test_directory);
+ ok(ret == 0, "Test directory is empty");
+end:
+ fd_tracker_destroy(tracker);
+ free(test_directory);
+ free(unlinked_files_directory);
+ free(unlinked_file_zero);
+ free(unlinked_file_one);
+ lttng_directory_handle_put(dir_handle);
+}
+
+int main(int argc, char **argv)
+{
+ plan_tests(NUM_TESTS);
+ diag("File descriptor tracker unit tests");
+
+ rcu_register_thread();
+
+ unknown_fds_count = fd_count() - STDIO_FD_COUNT;
+ LTTNG_ASSERT(unknown_fds_count >= 0);
+
+ diag("Unsuspendable - basic");
+ test_unsuspendable_basic();
+ diag("Unsuspendable - callback return values");
+ test_unsuspendable_cb_return();
+ diag("Unsuspendable - duplicate file descriptors");
+ test_unsuspendable_duplicate();
+ diag("Unsuspendable - closing an untracked file descriptor");
+ test_unsuspendable_close_untracked();
+ diag("Unsuspendable - check that file descriptor limit is enforced");
+ test_unsuspendable_limit();
+
+ diag("Suspendable - check that file descriptor limit is enforced");
+ test_suspendable_limit();
+ diag("Suspendable - restoration test");
+ test_suspendable_restore();
+
+ diag("Mixed - check that file descriptor limit is enforced");
+ test_mixed_limit();
+
+ diag("Suspendable - Unlinking test");
+ test_unlink();
+
+ rcu_barrier();
+ rcu_unregister_thread();
+ return exit_status();
+}
+++ /dev/null
-/*
- * Unit tests for the kernel probe location API.
- *
- * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <tap/tap.h>
-
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/kernel-probe-internal.h>
-#include <lttng/kernel-probe.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-#define NUM_TESTS 24
-
-static void test_kernel_probe_location_address(void)
-{
- struct lttng_kernel_probe_location *location = NULL;
- struct lttng_kernel_probe_location *location_from_buffer = NULL;
- enum lttng_kernel_probe_location_status status;
- enum lttng_kernel_probe_location_type type;
- uint64_t address = 50, _address;
- struct lttng_payload payload;
-
- diag("Testing kernel probe location address");
-
- lttng_payload_init(&payload);
-
- location = lttng_kernel_probe_location_address_create(address);
- ok(location, "Location object");
-
- type = lttng_kernel_probe_location_get_type(location);
- ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS == type,
- "Location type got %d expected %d", type,
- LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
-
- status = lttng_kernel_probe_location_address_get_address(
- location, &_address);
- ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting address");
- ok(address == _address,
- "Address is equal. Got %" PRIu64 " expected %" PRIu64,
- _address, address);
-
- ok(lttng_kernel_probe_location_serialize(location, &payload) > 0,
- "Serializing");
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- ok(lttng_kernel_probe_location_create_from_payload(
- &view, &location_from_buffer) > 0,
- "Deserializing");
- }
-
- type = lttng_kernel_probe_location_get_type(location_from_buffer);
- ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS == type,
- "Location from buffer type got %d expected %d", type,
- LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
-
- status = lttng_kernel_probe_location_address_get_address(
- location_from_buffer, &_address);
- ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting address");
- ok(address == _address,
- "Address from buffer is equal. Got %" PRIu64
- " expected %" PRIu64,
- _address, address);
-
- ok(lttng_kernel_probe_location_is_equal(location, location_from_buffer),
- "serialized and from buffer are equal");
-
- lttng_payload_reset(&payload);
- lttng_kernel_probe_location_destroy(location);
- lttng_kernel_probe_location_destroy(location_from_buffer);
-}
-
-static void test_kernel_probe_location_symbol(void)
-{
- struct lttng_kernel_probe_location *location = NULL;
- struct lttng_kernel_probe_location *location_from_buffer = NULL;
- enum lttng_kernel_probe_location_status status;
- enum lttng_kernel_probe_location_type type;
- uint64_t offset = 50, _offset;
- const char *symbol = "Une_bonne", *_symbol;
- struct lttng_payload payload;
-
- diag("Testing kernel probe location symbol");
-
- lttng_payload_init(&payload);
-
- location = lttng_kernel_probe_location_symbol_create(symbol, offset);
- ok(location, "Location object");
-
- type = lttng_kernel_probe_location_get_type(location);
- ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET == type,
- "Location type got %d expected %d", type,
- LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
-
- _symbol = lttng_kernel_probe_location_symbol_get_name(location);
- ok(_symbol, "Getting symbol name");
- ok(!strncmp(symbol, _symbol, strlen(symbol)),
- "Symbol name is equal. Got %s, expected %s", _symbol,
- symbol);
-
- status = lttng_kernel_probe_location_symbol_get_offset(
- location, &_offset);
- ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting offset");
- ok(offset == _offset,
- "Offset is equal. Got %" PRIu64 " expected %" PRIu64,
- _offset, offset);
-
- ok(lttng_kernel_probe_location_serialize(location, &payload) > 0,
- "Serializing");
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- ok(lttng_kernel_probe_location_create_from_payload(
- &view, &location_from_buffer) > 0,
- "Deserializing");
- }
-
- type = lttng_kernel_probe_location_get_type(location_from_buffer);
- ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET == type,
- "Location from buffer type got %d expected %d", type,
- LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
-
- _symbol = lttng_kernel_probe_location_symbol_get_name(
- location_from_buffer);
- ok(_symbol, "Getting symbol name");
- ok(!strncmp(symbol, _symbol, strlen(symbol)),
- "Symbol name is equal. Got %s, expected %s", _symbol,
- symbol);
-
- status = lttng_kernel_probe_location_symbol_get_offset(
- location_from_buffer, &_offset);
- ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting offset");
- ok(offset == _offset,
- "Offset is equal. Got %" PRIu64 " expected %" PRIu64,
- _offset, offset);
-
- ok(lttng_kernel_probe_location_is_equal(location, location_from_buffer),
- "serialized and from buffer are equal");
-
- lttng_payload_reset(&payload);
- lttng_kernel_probe_location_destroy(location);
- lttng_kernel_probe_location_destroy(location_from_buffer);
-}
-
-int main(int argc, const char *argv[])
-{
- plan_tests(NUM_TESTS);
- test_kernel_probe_location_address();
- test_kernel_probe_location_symbol();
- return exit_status();
-}
--- /dev/null
+/*
+ * Unit tests for the kernel probe location API.
+ *
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/kernel-probe-internal.h>
+#include <lttng/kernel-probe.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 24
+
+static void test_kernel_probe_location_address(void)
+{
+ struct lttng_kernel_probe_location *location = NULL;
+ struct lttng_kernel_probe_location *location_from_buffer = NULL;
+ enum lttng_kernel_probe_location_status status;
+ enum lttng_kernel_probe_location_type type;
+ uint64_t address = 50, _address;
+ struct lttng_payload payload;
+
+ diag("Testing kernel probe location address");
+
+ lttng_payload_init(&payload);
+
+ location = lttng_kernel_probe_location_address_create(address);
+ ok(location, "Location object");
+
+ type = lttng_kernel_probe_location_get_type(location);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS == type,
+ "Location type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
+
+ status = lttng_kernel_probe_location_address_get_address(
+ location, &_address);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting address");
+ ok(address == _address,
+ "Address is equal. Got %" PRIu64 " expected %" PRIu64,
+ _address, address);
+
+ ok(lttng_kernel_probe_location_serialize(location, &payload) > 0,
+ "Serializing");
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ ok(lttng_kernel_probe_location_create_from_payload(
+ &view, &location_from_buffer) > 0,
+ "Deserializing");
+ }
+
+ type = lttng_kernel_probe_location_get_type(location_from_buffer);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS == type,
+ "Location from buffer type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
+
+ status = lttng_kernel_probe_location_address_get_address(
+ location_from_buffer, &_address);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting address");
+ ok(address == _address,
+ "Address from buffer is equal. Got %" PRIu64
+ " expected %" PRIu64,
+ _address, address);
+
+ ok(lttng_kernel_probe_location_is_equal(location, location_from_buffer),
+ "serialized and from buffer are equal");
+
+ lttng_payload_reset(&payload);
+ lttng_kernel_probe_location_destroy(location);
+ lttng_kernel_probe_location_destroy(location_from_buffer);
+}
+
+static void test_kernel_probe_location_symbol(void)
+{
+ struct lttng_kernel_probe_location *location = NULL;
+ struct lttng_kernel_probe_location *location_from_buffer = NULL;
+ enum lttng_kernel_probe_location_status status;
+ enum lttng_kernel_probe_location_type type;
+ uint64_t offset = 50, _offset;
+ const char *symbol = "Une_bonne", *_symbol;
+ struct lttng_payload payload;
+
+ diag("Testing kernel probe location symbol");
+
+ lttng_payload_init(&payload);
+
+ location = lttng_kernel_probe_location_symbol_create(symbol, offset);
+ ok(location, "Location object");
+
+ type = lttng_kernel_probe_location_get_type(location);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET == type,
+ "Location type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
+
+ _symbol = lttng_kernel_probe_location_symbol_get_name(location);
+ ok(_symbol, "Getting symbol name");
+ ok(!strncmp(symbol, _symbol, strlen(symbol)),
+ "Symbol name is equal. Got %s, expected %s", _symbol,
+ symbol);
+
+ status = lttng_kernel_probe_location_symbol_get_offset(
+ location, &_offset);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting offset");
+ ok(offset == _offset,
+ "Offset is equal. Got %" PRIu64 " expected %" PRIu64,
+ _offset, offset);
+
+ ok(lttng_kernel_probe_location_serialize(location, &payload) > 0,
+ "Serializing");
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ ok(lttng_kernel_probe_location_create_from_payload(
+ &view, &location_from_buffer) > 0,
+ "Deserializing");
+ }
+
+ type = lttng_kernel_probe_location_get_type(location_from_buffer);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET == type,
+ "Location from buffer type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
+
+ _symbol = lttng_kernel_probe_location_symbol_get_name(
+ location_from_buffer);
+ ok(_symbol, "Getting symbol name");
+ ok(!strncmp(symbol, _symbol, strlen(symbol)),
+ "Symbol name is equal. Got %s, expected %s", _symbol,
+ symbol);
+
+ status = lttng_kernel_probe_location_symbol_get_offset(
+ location_from_buffer, &_offset);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting offset");
+ ok(offset == _offset,
+ "Offset is equal. Got %" PRIu64 " expected %" PRIu64,
+ _offset, offset);
+
+ ok(lttng_kernel_probe_location_is_equal(location, location_from_buffer),
+ "serialized and from buffer are equal");
+
+ lttng_payload_reset(&payload);
+ lttng_kernel_probe_location_destroy(location);
+ lttng_kernel_probe_location_destroy(location_from_buffer);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_kernel_probe_location_address();
+ test_kernel_probe_location_symbol();
+ return exit_status();
+}
+++ /dev/null
-/*
- * Unit tests for the log level rule API.
- *
- * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <tap/tap.h>
-
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/log-level-rule-internal.h>
-#include <lttng/log-level-rule.h>
-
-/* For error.h. */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-#define NUM_TESTS 29
-
-static void test_log_level_rule_error(void)
-{
- int level = 9000;
- struct lttng_log_level_rule *exactly =
- lttng_log_level_rule_exactly_create(level);
- struct lttng_log_level_rule *at_least_as_severe =
- lttng_log_level_rule_at_least_as_severe_as_create(
- level);
-
- ok(lttng_log_level_rule_get_type(NULL) == LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN, "Get type on invalid pointer");
-
- ok(lttng_log_level_rule_exactly_get_level(NULL, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (NULL, NULL) returns invalid");
- ok(lttng_log_level_rule_exactly_get_level(exactly, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (valid, NULL) returns invalid");
- ok(lttng_log_level_rule_exactly_get_level(NULL, &level) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (NULL, valid) returns invalid");
-
- ok(lttng_log_level_rule_at_least_as_severe_as_get_level(NULL, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (NULL, NULL) returns invalid");
- ok(lttng_log_level_rule_at_least_as_severe_as_get_level(exactly, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (valid, NULL) returns invalid");
- ok(lttng_log_level_rule_at_least_as_severe_as_get_level(NULL, &level) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (NULL, valid) returns invalid");
-
- lttng_log_level_rule_destroy(exactly);
- lttng_log_level_rule_destroy(at_least_as_severe);
-}
-
-static
-void test_log_level_rule_serialize_deserialize(const struct lttng_log_level_rule *rule)
-{
- struct lttng_log_level_rule *log_level_rule_from_buffer = NULL;
- struct lttng_payload payload;
-
- lttng_payload_init(&payload);
-
- ok(lttng_log_level_rule_serialize(rule, &payload) == 0, "Serializing.");
-
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_log_level_rule_create_from_payload(
- &view, &log_level_rule_from_buffer) > 0,
- "Deserializing.");
- }
-
- ok(lttng_log_level_rule_is_equal(rule, log_level_rule_from_buffer), "Serialized and from buffer are equal");
-
- lttng_log_level_rule_destroy(log_level_rule_from_buffer);
-}
-
-static
-void test_log_level_rule_is_equal_exactly(void)
-{
- int level = 9000, no_eq_level = 420;
- struct lttng_log_level_rule *a, *b, *different_level, *different_type;
-
- /* Identical log level rules. */
- a = lttng_log_level_rule_exactly_create(level);
- b = lttng_log_level_rule_exactly_create(level);
-
- /* Different level, same type. */
- different_level = lttng_log_level_rule_exactly_create(no_eq_level);
-
- /* Different type. */
- different_type = lttng_log_level_rule_at_least_as_severe_as_create(level);
-
- LTTNG_ASSERT(a && b && different_level && different_type);
-
- ok(lttng_log_level_rule_is_equal(a, a), "Same object is equal");
- ok(lttng_log_level_rule_is_equal(a, b), "Object a and b are equal");
- ok(!lttng_log_level_rule_is_equal(a, different_level), " Object of different levels are not equal");
- ok(!lttng_log_level_rule_is_equal(a, different_type), " Object of different types are not equal");
-
- lttng_log_level_rule_destroy(a);
- lttng_log_level_rule_destroy(b);
- lttng_log_level_rule_destroy(different_level);
- lttng_log_level_rule_destroy(different_type);
-}
-
-static
-void test_log_level_rule_is_equal_at_least_as_severe_as(void)
-{
- int level = 9000, no_eq_level = 420;
- struct lttng_log_level_rule *a, *b, *different_level, *different_type;
-
- /* Identical log level rules. */
- a = lttng_log_level_rule_at_least_as_severe_as_create(level);
- b = lttng_log_level_rule_at_least_as_severe_as_create(level);
-
- /* Different level, same type. */
- different_level = lttng_log_level_rule_at_least_as_severe_as_create(no_eq_level);
-
- /* Different type. */
- different_type = lttng_log_level_rule_exactly_create(level);
-
- LTTNG_ASSERT(a && b && different_level && different_type);
-
- ok(lttng_log_level_rule_is_equal(a, a), "Same object is equal");
- ok(lttng_log_level_rule_is_equal(a, b), "Object a and b are equal");
- ok(!lttng_log_level_rule_is_equal(a, different_level), " Object of different levels are not equal");
- ok(!lttng_log_level_rule_is_equal(a, different_type), " Object of different types are not equal");
-
- lttng_log_level_rule_destroy(a);
- lttng_log_level_rule_destroy(b);
- lttng_log_level_rule_destroy(different_level);
- lttng_log_level_rule_destroy(different_type);
-}
-
-static void test_log_level_rule_exactly(void)
-{
- int level = 9000;
- int _level;
- struct lttng_log_level_rule *exactly = NULL;
- enum lttng_log_level_rule_status status;
-
- exactly = lttng_log_level_rule_exactly_create(level);
-
- ok(exactly, "Log level exactly allocated");
- ok(lttng_log_level_rule_get_type(exactly) ==
- LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY,
- "Log level rule exactly type");
-
- status = lttng_log_level_rule_exactly_get_level(exactly, &_level);
- ok(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK, "Get the level");
- ok(_level == level, "Level property is valid");
-
- test_log_level_rule_is_equal_exactly();
- test_log_level_rule_serialize_deserialize(exactly);
- lttng_log_level_rule_destroy(exactly);
-}
-
-static void test_log_level_rule_at_least_as_severe_as(void)
-{
- int level = 9000;
- int _level;
- struct lttng_log_level_rule *at_least_as_severe_as = NULL;
- enum lttng_log_level_rule_status status;
-
- at_least_as_severe_as = lttng_log_level_rule_at_least_as_severe_as_create(level);
-
- ok(at_least_as_severe_as, "Log level at_least_as_severe_as allocated");
- ok(lttng_log_level_rule_get_type(at_least_as_severe_as) ==
- LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS,
- "Log level rule at_least_as_severe_as type");
-
- status = lttng_log_level_rule_at_least_as_severe_as_get_level(at_least_as_severe_as, &_level);
- ok(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK, "Get the level");
- ok(_level == level, "Level property is valid");
-
- test_log_level_rule_is_equal_at_least_as_severe_as();
- test_log_level_rule_serialize_deserialize(at_least_as_severe_as);
- lttng_log_level_rule_destroy(at_least_as_severe_as);
-}
-
-int main(int argc, const char *argv[])
-{
- plan_tests(NUM_TESTS);
- test_log_level_rule_exactly();
- test_log_level_rule_at_least_as_severe_as();
- test_log_level_rule_error();
- return exit_status();
-}
--- /dev/null
+/*
+ * Unit tests for the log level rule API.
+ *
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/log-level-rule-internal.h>
+#include <lttng/log-level-rule.h>
+
+/* For error.h. */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 29
+
+static void test_log_level_rule_error(void)
+{
+ int level = 9000;
+ struct lttng_log_level_rule *exactly =
+ lttng_log_level_rule_exactly_create(level);
+ struct lttng_log_level_rule *at_least_as_severe =
+ lttng_log_level_rule_at_least_as_severe_as_create(
+ level);
+
+ ok(lttng_log_level_rule_get_type(NULL) == LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN, "Get type on invalid pointer");
+
+ ok(lttng_log_level_rule_exactly_get_level(NULL, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (NULL, NULL) returns invalid");
+ ok(lttng_log_level_rule_exactly_get_level(exactly, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (valid, NULL) returns invalid");
+ ok(lttng_log_level_rule_exactly_get_level(NULL, &level) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (NULL, valid) returns invalid");
+
+ ok(lttng_log_level_rule_at_least_as_severe_as_get_level(NULL, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (NULL, NULL) returns invalid");
+ ok(lttng_log_level_rule_at_least_as_severe_as_get_level(exactly, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (valid, NULL) returns invalid");
+ ok(lttng_log_level_rule_at_least_as_severe_as_get_level(NULL, &level) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (NULL, valid) returns invalid");
+
+ lttng_log_level_rule_destroy(exactly);
+ lttng_log_level_rule_destroy(at_least_as_severe);
+}
+
+static
+void test_log_level_rule_serialize_deserialize(const struct lttng_log_level_rule *rule)
+{
+ struct lttng_log_level_rule *log_level_rule_from_buffer = NULL;
+ struct lttng_payload payload;
+
+ lttng_payload_init(&payload);
+
+ ok(lttng_log_level_rule_serialize(rule, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_log_level_rule_create_from_payload(
+ &view, &log_level_rule_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_log_level_rule_is_equal(rule, log_level_rule_from_buffer), "Serialized and from buffer are equal");
+
+ lttng_log_level_rule_destroy(log_level_rule_from_buffer);
+}
+
+static
+void test_log_level_rule_is_equal_exactly(void)
+{
+ int level = 9000, no_eq_level = 420;
+ struct lttng_log_level_rule *a, *b, *different_level, *different_type;
+
+ /* Identical log level rules. */
+ a = lttng_log_level_rule_exactly_create(level);
+ b = lttng_log_level_rule_exactly_create(level);
+
+ /* Different level, same type. */
+ different_level = lttng_log_level_rule_exactly_create(no_eq_level);
+
+ /* Different type. */
+ different_type = lttng_log_level_rule_at_least_as_severe_as_create(level);
+
+ LTTNG_ASSERT(a && b && different_level && different_type);
+
+ ok(lttng_log_level_rule_is_equal(a, a), "Same object is equal");
+ ok(lttng_log_level_rule_is_equal(a, b), "Object a and b are equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_level), " Object of different levels are not equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_type), " Object of different types are not equal");
+
+ lttng_log_level_rule_destroy(a);
+ lttng_log_level_rule_destroy(b);
+ lttng_log_level_rule_destroy(different_level);
+ lttng_log_level_rule_destroy(different_type);
+}
+
+static
+void test_log_level_rule_is_equal_at_least_as_severe_as(void)
+{
+ int level = 9000, no_eq_level = 420;
+ struct lttng_log_level_rule *a, *b, *different_level, *different_type;
+
+ /* Identical log level rules. */
+ a = lttng_log_level_rule_at_least_as_severe_as_create(level);
+ b = lttng_log_level_rule_at_least_as_severe_as_create(level);
+
+ /* Different level, same type. */
+ different_level = lttng_log_level_rule_at_least_as_severe_as_create(no_eq_level);
+
+ /* Different type. */
+ different_type = lttng_log_level_rule_exactly_create(level);
+
+ LTTNG_ASSERT(a && b && different_level && different_type);
+
+ ok(lttng_log_level_rule_is_equal(a, a), "Same object is equal");
+ ok(lttng_log_level_rule_is_equal(a, b), "Object a and b are equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_level), " Object of different levels are not equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_type), " Object of different types are not equal");
+
+ lttng_log_level_rule_destroy(a);
+ lttng_log_level_rule_destroy(b);
+ lttng_log_level_rule_destroy(different_level);
+ lttng_log_level_rule_destroy(different_type);
+}
+
+static void test_log_level_rule_exactly(void)
+{
+ int level = 9000;
+ int _level;
+ struct lttng_log_level_rule *exactly = NULL;
+ enum lttng_log_level_rule_status status;
+
+ exactly = lttng_log_level_rule_exactly_create(level);
+
+ ok(exactly, "Log level exactly allocated");
+ ok(lttng_log_level_rule_get_type(exactly) ==
+ LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY,
+ "Log level rule exactly type");
+
+ status = lttng_log_level_rule_exactly_get_level(exactly, &_level);
+ ok(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK, "Get the level");
+ ok(_level == level, "Level property is valid");
+
+ test_log_level_rule_is_equal_exactly();
+ test_log_level_rule_serialize_deserialize(exactly);
+ lttng_log_level_rule_destroy(exactly);
+}
+
+static void test_log_level_rule_at_least_as_severe_as(void)
+{
+ int level = 9000;
+ int _level;
+ struct lttng_log_level_rule *at_least_as_severe_as = NULL;
+ enum lttng_log_level_rule_status status;
+
+ at_least_as_severe_as = lttng_log_level_rule_at_least_as_severe_as_create(level);
+
+ ok(at_least_as_severe_as, "Log level at_least_as_severe_as allocated");
+ ok(lttng_log_level_rule_get_type(at_least_as_severe_as) ==
+ LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS,
+ "Log level rule at_least_as_severe_as type");
+
+ status = lttng_log_level_rule_at_least_as_severe_as_get_level(at_least_as_severe_as, &_level);
+ ok(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK, "Get the level");
+ ok(_level == level, "Level property is valid");
+
+ test_log_level_rule_is_equal_at_least_as_severe_as();
+ test_log_level_rule_serialize_deserialize(at_least_as_severe_as);
+ lttng_log_level_rule_destroy(at_least_as_severe_as);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_log_level_rule_exactly();
+ test_log_level_rule_at_least_as_severe_as();
+ test_log_level_rule_error();
+ return exit_status();
+}
+++ /dev/null
-/*
- * test_notification.c
- *
- * Unit tests for the notification API.
- *
- * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <tap/tap.h>
-
-#include <lttng/action/action.h>
-#include <lttng/action/notify.h>
-#include <lttng/condition/buffer-usage.h>
-#include <lttng/condition/condition.h>
-#include <lttng/domain.h>
-#include <lttng/notification/notification.h>
-#include <lttng/trigger/trigger.h>
-
-#include <common/macros.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-#define NUM_TESTS 180
-
-static void test_condition_buffer_usage(
- struct lttng_condition *buffer_usage_condition)
-{
- enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
- const char *session_name = NULL;
- const char *channel_name = NULL;
- enum lttng_domain_type domain_type;
- /* Start at a non zero value to validate initialization */
- double threshold_ratio;
- uint64_t threshold_bytes;
-
- LTTNG_ASSERT(buffer_usage_condition);
-
- diag("Validating initialization");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
-
- status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold byte is unset");
-
- status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
- ok(!session_name, "Session name is null");
-
- status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
- ok(!session_name, "Channel name is null");
-
- status = lttng_condition_buffer_usage_get_domain_type(buffer_usage_condition, &domain_type);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Domain name is unset");
-
- diag("Testing session name set/get");
- status = lttng_condition_buffer_usage_set_session_name(NULL, "Test");
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null condition on set session name");
- status = lttng_condition_buffer_usage_get_session_name(NULL, &session_name);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get session name with null condition");
- ok(!session_name, "Session name is null");
- status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
- ok(!session_name, "Session name is null");
-
- status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, NULL);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null session name");
- status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
- ok(!session_name, "Session name is null");
-
- status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, "");
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set empty session name");
- status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
- ok(!session_name, "Session name is null");
-
- status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, "session420");
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set session name session420");
- status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Session name is set");
- ok(session_name, "Session name has a value");
- ok(strcmp("session420", session_name) == 0, "Session name is %s", "session420");
-
- /*
- * Test second set on session_name. Test invalid set and validate that
- * the value is still the previous good one.
- */
-
- status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, "");
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set session name to empty");
- status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Session name is still set");
- ok(session_name, "Session name has a value");
- ok(strcmp("session420", session_name) == 0, "Session is still name is %s", "session420");
-
- diag("Testing channel name set/get");
- status = lttng_condition_buffer_usage_set_channel_name(NULL, "Test");
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null condition on set channel name");
- status = lttng_condition_buffer_usage_get_channel_name(NULL, &channel_name);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get channel name with null condition");
- status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
- ok(!channel_name, "Channel name is null");
-
- status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, NULL);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null channel name");
- status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
- ok(!channel_name, "Channel name is null");
-
- status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, "");
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set empty channel name");
- status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
- ok(!channel_name, "Channel name is null");
-
- status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, "channel420");
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set channel name channel420");
- status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Channel name is set");
- ok(channel_name, "Channel name has a value");
- ok(strcmp("channel420", channel_name) == 0, "Channel name is %s", "channel420");
-
- /*
- * Test second set on channel_name. Test invalid set and validate that
- * the value is still the previous good one.
- */
-
- status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, "");
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set channel name to empty");
- status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Channel name is still set");
- ok(channel_name, "Channel name has a value");
- ok(strcmp("channel420", channel_name) == 0, "Channel is still name is %s", "channel420");
-
- diag("Testing threshold ratio set/get");
- status = lttng_condition_buffer_usage_set_threshold_ratio(NULL, 0.420);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set threshold ratio with null condition");
- status = lttng_condition_buffer_usage_get_threshold_ratio(NULL, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get threshold ratio with null condition");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
-
- status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, -100.0);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set threshold ratio < 0");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
-
- status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 200.0);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set Threshold ratio > 1");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
-
- status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 1.0);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 1.0");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
- ok(threshold_ratio == 1.0, "Threshold ratio is 1.0");
-
- status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 0.0);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 0.0");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
- ok(threshold_ratio == 0.0, "Threshold ratio is 0.0");
-
- status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 0.420);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 0.420");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
- ok(threshold_ratio == 0.420, "Threshold ratio is 0.420");
-
- diag("Testing threshold bytes set/get");
- status = lttng_condition_buffer_usage_set_threshold(NULL, 100000);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set threshold with null condition");
- status = lttng_condition_buffer_usage_get_threshold(NULL, &threshold_bytes);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get threshold value with null condition ");
- status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold is unset");
-
- status = lttng_condition_buffer_usage_set_threshold(buffer_usage_condition, 100000);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold > 0");
- status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold is set");
- ok(threshold_bytes == 100000, "Threshold is %" PRIu64 , 100000);
-
- status = lttng_condition_buffer_usage_set_threshold(buffer_usage_condition, UINT64_MAX);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold UINT64_MAX");
- status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold is set");
- ok(threshold_bytes == UINT64_MAX, "Threshold is UINT64_MAX");
-
- status = lttng_condition_buffer_usage_set_threshold(buffer_usage_condition, 0);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold == 0");
- status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold is set");
- ok(threshold_bytes == 0, "Threshold is %d", 0);
-
- /*
- * Test value of threshold ration, since we overwrote it with a byte
- * threshold. Make sure it gets squashed.
- */
- diag("Testing interaction between byte and ratio thresholds");
-
- threshold_ratio = -1.0;
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
- ok(threshold_ratio == -1.0, "Threshold ratio is untouched");
-
- /* Set a ratio to validate that the byte threshold is now unset */
- status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 0.420);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 0.420");
- status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
- ok(threshold_ratio == 0.420, "Threshold ratio is 0.420");
-
- threshold_bytes = 420;
- status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold is unset");
- ok(threshold_bytes == 420, "Threshold is untouched");
-
- diag("Testing domain type set/get");
- status = lttng_condition_buffer_usage_set_domain_type(NULL, LTTNG_DOMAIN_UST);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set domain type with null condition");
- status = lttng_condition_buffer_usage_get_domain_type(NULL, &domain_type);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get domain type with null condition");
-
- status = lttng_condition_buffer_usage_set_domain_type(buffer_usage_condition, LTTNG_DOMAIN_NONE);
- ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set domain type as LTTNG_DOMAIN_NONE");
- status = lttng_condition_buffer_usage_get_domain_type(buffer_usage_condition, &domain_type);
- ok(status == LTTNG_CONDITION_STATUS_UNSET, "Domain type is unset");
-
- status = lttng_condition_buffer_usage_set_domain_type(buffer_usage_condition, LTTNG_DOMAIN_UST);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Set domain type as LTTNG_DOMAIN_UST");
- status = lttng_condition_buffer_usage_get_domain_type(buffer_usage_condition, &domain_type);
- ok(status == LTTNG_CONDITION_STATUS_OK, "Domain type is set");
- ok(domain_type == LTTNG_DOMAIN_UST, "Domain type is LTTNG_DOMAIN_UST");
-}
-
-static void test_condition_buffer_usage_low(void)
-{
- struct lttng_condition *buffer_usage_low = NULL;
-
- diag("Testing lttng_condition_buffer_usage_low_create");
- buffer_usage_low = lttng_condition_buffer_usage_low_create();
- ok(buffer_usage_low, "Condition allocated");
-
- ok(lttng_condition_get_type(buffer_usage_low) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW, "Condition is of type \"low buffer usage\"");
-
- test_condition_buffer_usage(buffer_usage_low);
-
- lttng_condition_destroy(buffer_usage_low);
-}
-
-static void test_condition_buffer_usage_high(void)
-{
- struct lttng_condition *buffer_usage_high = NULL;
-
- diag("Testing lttng_condition_buffer_usage_high_create");
- buffer_usage_high = lttng_condition_buffer_usage_high_create();
- ok(buffer_usage_high, "High buffer usage condition allocated");
-
- ok(lttng_condition_get_type(buffer_usage_high) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH, "Condition is of type \"high buffer usage\"");
-
- test_condition_buffer_usage(buffer_usage_high);
-
- lttng_condition_destroy(buffer_usage_high);
-}
-
-static void test_trigger(void)
-{
- struct lttng_action *notify_action = NULL;
- struct lttng_condition *buffer_usage_high = NULL;
- struct lttng_trigger *trigger = NULL;
-
- notify_action = lttng_action_notify_create();
- buffer_usage_high = lttng_condition_buffer_usage_high_create();
-
- trigger = lttng_trigger_create(NULL, NULL);
- ok(!trigger, "lttng_trigger_create(NULL, NULL) returns null");
- trigger = lttng_trigger_create(buffer_usage_high, NULL);
- ok(!trigger, "lttng_trigger_create(NON-NULL, NULL) returns null");
- trigger = lttng_trigger_create(NULL, notify_action);
- ok(!trigger, "lttng_trigger_create(NULL, NON-NULL) returns null");
-
- trigger = lttng_trigger_create(buffer_usage_high, notify_action);
- ok(trigger, "lttng_trigger_create(NON-NULL, NON-NULL) returns an object");
-
- lttng_action_destroy(notify_action);
- lttng_condition_destroy(buffer_usage_high);
- lttng_trigger_destroy(trigger);
-}
-
-
-int main(int argc, const char *argv[])
-{
- plan_tests(NUM_TESTS);
- test_condition_buffer_usage_low();
- test_condition_buffer_usage_high();
- test_trigger();
- return exit_status();
-}
--- /dev/null
+/*
+ * test_notification.c
+ *
+ * Unit tests for the notification API.
+ *
+ * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <lttng/action/action.h>
+#include <lttng/action/notify.h>
+#include <lttng/condition/buffer-usage.h>
+#include <lttng/condition/condition.h>
+#include <lttng/domain.h>
+#include <lttng/notification/notification.h>
+#include <lttng/trigger/trigger.h>
+
+#include <common/macros.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 180
+
+static void test_condition_buffer_usage(
+ struct lttng_condition *buffer_usage_condition)
+{
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+ const char *session_name = NULL;
+ const char *channel_name = NULL;
+ enum lttng_domain_type domain_type;
+ /* Start at a non zero value to validate initialization */
+ double threshold_ratio;
+ uint64_t threshold_bytes;
+
+ LTTNG_ASSERT(buffer_usage_condition);
+
+ diag("Validating initialization");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
+
+ status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold byte is unset");
+
+ status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
+ ok(!session_name, "Session name is null");
+
+ status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
+ ok(!session_name, "Channel name is null");
+
+ status = lttng_condition_buffer_usage_get_domain_type(buffer_usage_condition, &domain_type);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Domain name is unset");
+
+ diag("Testing session name set/get");
+ status = lttng_condition_buffer_usage_set_session_name(NULL, "Test");
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null condition on set session name");
+ status = lttng_condition_buffer_usage_get_session_name(NULL, &session_name);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get session name with null condition");
+ ok(!session_name, "Session name is null");
+ status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
+ ok(!session_name, "Session name is null");
+
+ status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, NULL);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null session name");
+ status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
+ ok(!session_name, "Session name is null");
+
+ status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, "");
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set empty session name");
+ status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Session name is unset");
+ ok(!session_name, "Session name is null");
+
+ status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, "session420");
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set session name session420");
+ status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Session name is set");
+ ok(session_name, "Session name has a value");
+ ok(strcmp("session420", session_name) == 0, "Session name is %s", "session420");
+
+ /*
+ * Test second set on session_name. Test invalid set and validate that
+ * the value is still the previous good one.
+ */
+
+ status = lttng_condition_buffer_usage_set_session_name(buffer_usage_condition, "");
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set session name to empty");
+ status = lttng_condition_buffer_usage_get_session_name(buffer_usage_condition, &session_name);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Session name is still set");
+ ok(session_name, "Session name has a value");
+ ok(strcmp("session420", session_name) == 0, "Session is still name is %s", "session420");
+
+ diag("Testing channel name set/get");
+ status = lttng_condition_buffer_usage_set_channel_name(NULL, "Test");
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null condition on set channel name");
+ status = lttng_condition_buffer_usage_get_channel_name(NULL, &channel_name);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get channel name with null condition");
+ status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
+ ok(!channel_name, "Channel name is null");
+
+ status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, NULL);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set null channel name");
+ status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
+ ok(!channel_name, "Channel name is null");
+
+ status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, "");
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set empty channel name");
+ status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Channel name is unset");
+ ok(!channel_name, "Channel name is null");
+
+ status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, "channel420");
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set channel name channel420");
+ status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Channel name is set");
+ ok(channel_name, "Channel name has a value");
+ ok(strcmp("channel420", channel_name) == 0, "Channel name is %s", "channel420");
+
+ /*
+ * Test second set on channel_name. Test invalid set and validate that
+ * the value is still the previous good one.
+ */
+
+ status = lttng_condition_buffer_usage_set_channel_name(buffer_usage_condition, "");
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set channel name to empty");
+ status = lttng_condition_buffer_usage_get_channel_name(buffer_usage_condition, &channel_name);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Channel name is still set");
+ ok(channel_name, "Channel name has a value");
+ ok(strcmp("channel420", channel_name) == 0, "Channel is still name is %s", "channel420");
+
+ diag("Testing threshold ratio set/get");
+ status = lttng_condition_buffer_usage_set_threshold_ratio(NULL, 0.420);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set threshold ratio with null condition");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(NULL, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get threshold ratio with null condition");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
+
+ status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, -100.0);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set threshold ratio < 0");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
+
+ status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 200.0);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set Threshold ratio > 1");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
+
+ status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 1.0);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 1.0");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
+ ok(threshold_ratio == 1.0, "Threshold ratio is 1.0");
+
+ status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 0.0);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 0.0");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
+ ok(threshold_ratio == 0.0, "Threshold ratio is 0.0");
+
+ status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 0.420);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 0.420");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
+ ok(threshold_ratio == 0.420, "Threshold ratio is 0.420");
+
+ diag("Testing threshold bytes set/get");
+ status = lttng_condition_buffer_usage_set_threshold(NULL, 100000);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set threshold with null condition");
+ status = lttng_condition_buffer_usage_get_threshold(NULL, &threshold_bytes);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get threshold value with null condition ");
+ status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold is unset");
+
+ status = lttng_condition_buffer_usage_set_threshold(buffer_usage_condition, 100000);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold > 0");
+ status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold is set");
+ ok(threshold_bytes == 100000, "Threshold is %" PRIu64 , 100000);
+
+ status = lttng_condition_buffer_usage_set_threshold(buffer_usage_condition, UINT64_MAX);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold UINT64_MAX");
+ status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold is set");
+ ok(threshold_bytes == UINT64_MAX, "Threshold is UINT64_MAX");
+
+ status = lttng_condition_buffer_usage_set_threshold(buffer_usage_condition, 0);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold == 0");
+ status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold is set");
+ ok(threshold_bytes == 0, "Threshold is %d", 0);
+
+ /*
+ * Test value of threshold ration, since we overwrote it with a byte
+ * threshold. Make sure it gets squashed.
+ */
+ diag("Testing interaction between byte and ratio thresholds");
+
+ threshold_ratio = -1.0;
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold ratio is unset");
+ ok(threshold_ratio == -1.0, "Threshold ratio is untouched");
+
+ /* Set a ratio to validate that the byte threshold is now unset */
+ status = lttng_condition_buffer_usage_set_threshold_ratio(buffer_usage_condition, 0.420);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set threshold ratio == 0.420");
+ status = lttng_condition_buffer_usage_get_threshold_ratio(buffer_usage_condition, &threshold_ratio);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Threshold ratio is set");
+ ok(threshold_ratio == 0.420, "Threshold ratio is 0.420");
+
+ threshold_bytes = 420;
+ status = lttng_condition_buffer_usage_get_threshold(buffer_usage_condition, &threshold_bytes);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Threshold is unset");
+ ok(threshold_bytes == 420, "Threshold is untouched");
+
+ diag("Testing domain type set/get");
+ status = lttng_condition_buffer_usage_set_domain_type(NULL, LTTNG_DOMAIN_UST);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set domain type with null condition");
+ status = lttng_condition_buffer_usage_get_domain_type(NULL, &domain_type);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Get domain type with null condition");
+
+ status = lttng_condition_buffer_usage_set_domain_type(buffer_usage_condition, LTTNG_DOMAIN_NONE);
+ ok(status == LTTNG_CONDITION_STATUS_INVALID, "Set domain type as LTTNG_DOMAIN_NONE");
+ status = lttng_condition_buffer_usage_get_domain_type(buffer_usage_condition, &domain_type);
+ ok(status == LTTNG_CONDITION_STATUS_UNSET, "Domain type is unset");
+
+ status = lttng_condition_buffer_usage_set_domain_type(buffer_usage_condition, LTTNG_DOMAIN_UST);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Set domain type as LTTNG_DOMAIN_UST");
+ status = lttng_condition_buffer_usage_get_domain_type(buffer_usage_condition, &domain_type);
+ ok(status == LTTNG_CONDITION_STATUS_OK, "Domain type is set");
+ ok(domain_type == LTTNG_DOMAIN_UST, "Domain type is LTTNG_DOMAIN_UST");
+}
+
+static void test_condition_buffer_usage_low(void)
+{
+ struct lttng_condition *buffer_usage_low = NULL;
+
+ diag("Testing lttng_condition_buffer_usage_low_create");
+ buffer_usage_low = lttng_condition_buffer_usage_low_create();
+ ok(buffer_usage_low, "Condition allocated");
+
+ ok(lttng_condition_get_type(buffer_usage_low) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW, "Condition is of type \"low buffer usage\"");
+
+ test_condition_buffer_usage(buffer_usage_low);
+
+ lttng_condition_destroy(buffer_usage_low);
+}
+
+static void test_condition_buffer_usage_high(void)
+{
+ struct lttng_condition *buffer_usage_high = NULL;
+
+ diag("Testing lttng_condition_buffer_usage_high_create");
+ buffer_usage_high = lttng_condition_buffer_usage_high_create();
+ ok(buffer_usage_high, "High buffer usage condition allocated");
+
+ ok(lttng_condition_get_type(buffer_usage_high) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH, "Condition is of type \"high buffer usage\"");
+
+ test_condition_buffer_usage(buffer_usage_high);
+
+ lttng_condition_destroy(buffer_usage_high);
+}
+
+static void test_trigger(void)
+{
+ struct lttng_action *notify_action = NULL;
+ struct lttng_condition *buffer_usage_high = NULL;
+ struct lttng_trigger *trigger = NULL;
+
+ notify_action = lttng_action_notify_create();
+ buffer_usage_high = lttng_condition_buffer_usage_high_create();
+
+ trigger = lttng_trigger_create(NULL, NULL);
+ ok(!trigger, "lttng_trigger_create(NULL, NULL) returns null");
+ trigger = lttng_trigger_create(buffer_usage_high, NULL);
+ ok(!trigger, "lttng_trigger_create(NON-NULL, NULL) returns null");
+ trigger = lttng_trigger_create(NULL, notify_action);
+ ok(!trigger, "lttng_trigger_create(NULL, NON-NULL) returns null");
+
+ trigger = lttng_trigger_create(buffer_usage_high, notify_action);
+ ok(trigger, "lttng_trigger_create(NON-NULL, NON-NULL) returns an object");
+
+ lttng_action_destroy(notify_action);
+ lttng_condition_destroy(buffer_usage_high);
+ lttng_trigger_destroy(trigger);
+}
+
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_condition_buffer_usage_low();
+ test_condition_buffer_usage_high();
+ test_trigger();
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <unistd.h>
-
-#include <common/compat/fcntl.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-#include <tap/tap.h>
-
-static const int TEST_COUNT = 5;
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-static void test_fd_push_pop_order(void)
-{
- int ret, i;
- struct lttng_payload payload;
- int fds[3];
-
- lttng_payload_init(&payload);
-
- diag("Validating fd push/pop order");
- for (i = 0; i < 3; i++) {
- int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
- struct fd_handle *handle;
-
- LTTNG_ASSERT(fd >= 0);
- fds[i] = fd;
-
- handle = fd_handle_create(fd);
- LTTNG_ASSERT(handle);
-
- ret = lttng_payload_push_fd_handle(&payload, handle);
- fd_handle_put(handle);
- if (ret) {
- break;
- }
- }
-
- ok(ret == 0, "Added three file descriptors to an lttng_payload");
-
- {
- bool fail_pop = false;
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- for (i = 0; i < 3; i++) {
- struct fd_handle *handle =
- lttng_payload_view_pop_fd_handle(&view);
-
- fail_pop |= fd_handle_get_fd(handle) != fds[i];
- fd_handle_put(handle);
- }
-
- ok(!fail_pop, "File descriptors are popped from a payload view in the order of insertion");
- }
-
- lttng_payload_reset(&payload);
-}
-
-static void test_fd_push_pop_imbalance(void)
-{
- int ret, i;
- struct lttng_payload payload;
- const char * const test_description = "Error reported when popping more file descriptors than were pushed";
-
- lttng_payload_init(&payload);
-
- diag("Validating fd pop imbalance");
- for (i = 0; i < 10; i++) {
- struct fd_handle *handle;
- int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
-
- LTTNG_ASSERT(fd >= 0);
-
- handle = fd_handle_create(fd);
- LTTNG_ASSERT(handle);
-
- ret = lttng_payload_push_fd_handle(&payload, handle);
- fd_handle_put(handle);
- if (ret) {
- break;
- }
- }
-
- {
- struct fd_handle *handle;
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- for (i = 0; i < 10; i++) {
- handle = lttng_payload_view_pop_fd_handle(&view);
- fd_handle_put(handle);
- if (!handle) {
- goto fail;
- }
- }
-
- handle = lttng_payload_view_pop_fd_handle(&view);
- ok(!handle, test_description);
- fd_handle_put(handle);
- }
-
- lttng_payload_reset(&payload);
- return;
-fail:
- fail(test_description);
- lttng_payload_reset(&payload);
-}
-
-static void test_fd_pop_fd_root_views(void)
-{
- int ret, i;
- int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
- struct fd_handle *handle;
- struct lttng_payload payload;
- const char * const test_description = "Same file descriptor returned when popping from different top-level views";
-
- LTTNG_ASSERT(fd >= 0);
- handle = fd_handle_create(fd);
- LTTNG_ASSERT(handle);
-
- lttng_payload_init(&payload);
-
- diag("Validating root view fd pop behaviour");
- ret = lttng_payload_push_fd_handle(&payload, handle);
- if (ret) {
- goto fail;
- }
-
- for (i = 0; i < 5; i++) {
- int view_fd;
- struct fd_handle *view_handle;
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- view_handle = lttng_payload_view_pop_fd_handle(&view);
- if (!view_handle) {
- goto fail;
- }
-
- view_fd = fd_handle_get_fd(view_handle);
- fd_handle_put(view_handle);
- if (view_fd != fd || view_handle != handle) {
- goto fail;
- }
- }
-
- lttng_payload_reset(&payload);
- pass(test_description);
- fd_handle_put(handle);
- return;
-fail:
- lttng_payload_reset(&payload);
- fail(test_description);
- fd_handle_put(handle);
-}
-
-static void test_fd_pop_fd_descendant_views(void)
-{
- int ret;
- const int fd1 = 42, fd2 = 1837;
- struct fd_handle *handle1 = fd_handle_create(fd1);
- struct fd_handle *handle2 = fd_handle_create(fd2);
- struct fd_handle *view_handle1 = NULL, *view_handle2 = NULL;
- struct lttng_payload payload;
- const char * const test_description = "Different file descriptors returned when popping from descendant views";
-
- lttng_payload_init(&payload);
- LTTNG_ASSERT(handle1);
- LTTNG_ASSERT(handle2);
-
- diag("Validating descendant view fd pop behaviour");
- ret = lttng_payload_push_fd_handle(&payload, handle1);
- if (ret) {
- goto fail;
- }
-
- ret = lttng_payload_push_fd_handle(&payload, handle2);
- if (ret) {
- goto fail;
- }
-
- {
- struct lttng_payload_view view1 =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- struct lttng_payload_view view2 =
- lttng_payload_view_from_view(
- &view1, 0, -1);
-
- view_handle1 = lttng_payload_view_pop_fd_handle(&view1);
- if (!view_handle1 || fd_handle_get_fd(view_handle1) != fd1) {
- goto fail;
- }
-
- view_handle2 = lttng_payload_view_pop_fd_handle(&view2);
- if (!view_handle2 || fd_handle_get_fd(view_handle2) != fd2) {
- goto fail;
- }
- }
-
- lttng_payload_reset(&payload);
- pass(test_description);
- fd_handle_put(handle1);
- fd_handle_put(handle2);
- fd_handle_put(view_handle1);
- fd_handle_put(view_handle2);
- return;
-fail:
- lttng_payload_reset(&payload);
- fail(test_description);
- fd_handle_put(handle1);
- fd_handle_put(handle2);
- fd_handle_put(view_handle1);
- fd_handle_put(view_handle2);
-}
-
-int main(void)
-{
- plan_tests(TEST_COUNT);
-
- test_fd_push_pop_order();
- test_fd_push_pop_imbalance();
- test_fd_pop_fd_root_views();
- test_fd_pop_fd_descendant_views();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <unistd.h>
+
+#include <common/compat/fcntl.h>
+#include <common/payload.h>
+#include <common/payload-view.h>
+#include <tap/tap.h>
+
+static const int TEST_COUNT = 5;
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+static void test_fd_push_pop_order(void)
+{
+ int ret, i;
+ struct lttng_payload payload;
+ int fds[3];
+
+ lttng_payload_init(&payload);
+
+ diag("Validating fd push/pop order");
+ for (i = 0; i < 3; i++) {
+ int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
+ struct fd_handle *handle;
+
+ LTTNG_ASSERT(fd >= 0);
+ fds[i] = fd;
+
+ handle = fd_handle_create(fd);
+ LTTNG_ASSERT(handle);
+
+ ret = lttng_payload_push_fd_handle(&payload, handle);
+ fd_handle_put(handle);
+ if (ret) {
+ break;
+ }
+ }
+
+ ok(ret == 0, "Added three file descriptors to an lttng_payload");
+
+ {
+ bool fail_pop = false;
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ for (i = 0; i < 3; i++) {
+ struct fd_handle *handle =
+ lttng_payload_view_pop_fd_handle(&view);
+
+ fail_pop |= fd_handle_get_fd(handle) != fds[i];
+ fd_handle_put(handle);
+ }
+
+ ok(!fail_pop, "File descriptors are popped from a payload view in the order of insertion");
+ }
+
+ lttng_payload_reset(&payload);
+}
+
+static void test_fd_push_pop_imbalance(void)
+{
+ int ret, i;
+ struct lttng_payload payload;
+ const char * const test_description = "Error reported when popping more file descriptors than were pushed";
+
+ lttng_payload_init(&payload);
+
+ diag("Validating fd pop imbalance");
+ for (i = 0; i < 10; i++) {
+ struct fd_handle *handle;
+ int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
+
+ LTTNG_ASSERT(fd >= 0);
+
+ handle = fd_handle_create(fd);
+ LTTNG_ASSERT(handle);
+
+ ret = lttng_payload_push_fd_handle(&payload, handle);
+ fd_handle_put(handle);
+ if (ret) {
+ break;
+ }
+ }
+
+ {
+ struct fd_handle *handle;
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ for (i = 0; i < 10; i++) {
+ handle = lttng_payload_view_pop_fd_handle(&view);
+ fd_handle_put(handle);
+ if (!handle) {
+ goto fail;
+ }
+ }
+
+ handle = lttng_payload_view_pop_fd_handle(&view);
+ ok(!handle, test_description);
+ fd_handle_put(handle);
+ }
+
+ lttng_payload_reset(&payload);
+ return;
+fail:
+ fail(test_description);
+ lttng_payload_reset(&payload);
+}
+
+static void test_fd_pop_fd_root_views(void)
+{
+ int ret, i;
+ int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
+ struct fd_handle *handle;
+ struct lttng_payload payload;
+ const char * const test_description = "Same file descriptor returned when popping from different top-level views";
+
+ LTTNG_ASSERT(fd >= 0);
+ handle = fd_handle_create(fd);
+ LTTNG_ASSERT(handle);
+
+ lttng_payload_init(&payload);
+
+ diag("Validating root view fd pop behaviour");
+ ret = lttng_payload_push_fd_handle(&payload, handle);
+ if (ret) {
+ goto fail;
+ }
+
+ for (i = 0; i < 5; i++) {
+ int view_fd;
+ struct fd_handle *view_handle;
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ view_handle = lttng_payload_view_pop_fd_handle(&view);
+ if (!view_handle) {
+ goto fail;
+ }
+
+ view_fd = fd_handle_get_fd(view_handle);
+ fd_handle_put(view_handle);
+ if (view_fd != fd || view_handle != handle) {
+ goto fail;
+ }
+ }
+
+ lttng_payload_reset(&payload);
+ pass(test_description);
+ fd_handle_put(handle);
+ return;
+fail:
+ lttng_payload_reset(&payload);
+ fail(test_description);
+ fd_handle_put(handle);
+}
+
+static void test_fd_pop_fd_descendant_views(void)
+{
+ int ret;
+ const int fd1 = 42, fd2 = 1837;
+ struct fd_handle *handle1 = fd_handle_create(fd1);
+ struct fd_handle *handle2 = fd_handle_create(fd2);
+ struct fd_handle *view_handle1 = NULL, *view_handle2 = NULL;
+ struct lttng_payload payload;
+ const char * const test_description = "Different file descriptors returned when popping from descendant views";
+
+ lttng_payload_init(&payload);
+ LTTNG_ASSERT(handle1);
+ LTTNG_ASSERT(handle2);
+
+ diag("Validating descendant view fd pop behaviour");
+ ret = lttng_payload_push_fd_handle(&payload, handle1);
+ if (ret) {
+ goto fail;
+ }
+
+ ret = lttng_payload_push_fd_handle(&payload, handle2);
+ if (ret) {
+ goto fail;
+ }
+
+ {
+ struct lttng_payload_view view1 =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ struct lttng_payload_view view2 =
+ lttng_payload_view_from_view(
+ &view1, 0, -1);
+
+ view_handle1 = lttng_payload_view_pop_fd_handle(&view1);
+ if (!view_handle1 || fd_handle_get_fd(view_handle1) != fd1) {
+ goto fail;
+ }
+
+ view_handle2 = lttng_payload_view_pop_fd_handle(&view2);
+ if (!view_handle2 || fd_handle_get_fd(view_handle2) != fd2) {
+ goto fail;
+ }
+ }
+
+ lttng_payload_reset(&payload);
+ pass(test_description);
+ fd_handle_put(handle1);
+ fd_handle_put(handle2);
+ fd_handle_put(view_handle1);
+ fd_handle_put(view_handle2);
+ return;
+fail:
+ lttng_payload_reset(&payload);
+ fail(test_description);
+ fd_handle_put(handle1);
+ fd_handle_put(handle2);
+ fd_handle_put(view_handle1);
+ fd_handle_put(view_handle2);
+}
+
+int main(void)
+{
+ plan_tests(TEST_COUNT);
+
+ test_fd_push_pop_order();
+ test_fd_push_pop_imbalance();
+ test_fd_pop_fd_root_views();
+ test_fd_pop_fd_descendant_views();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * Unit tests for the rate policy object API.
- *
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <tap/tap.h>
-
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/action/rate-policy-internal.h>
-#include <lttng/action/rate-policy.h>
-
-/* For error.h. */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-#define NUM_TESTS 42
-
-static void test_rate_policy_every_n(void)
-{
- enum lttng_rate_policy_status status;
- struct lttng_rate_policy *policy_a = NULL; /* Interval of 100. */
- struct lttng_rate_policy *policy_b = NULL; /* Interval of 100 */
- struct lttng_rate_policy *policy_c = NULL; /* Interval of 1 */
- struct lttng_rate_policy *policy_from_buffer = NULL;
- uint64_t interval_a_b = 100;
- uint64_t interval_c = 1;
- uint64_t interval_query = 0;
- struct lttng_payload payload;
-
- lttng_payload_init(&payload);
-
- policy_a = lttng_rate_policy_every_n_create(interval_a_b);
- policy_b = lttng_rate_policy_every_n_create(interval_a_b);
- policy_c = lttng_rate_policy_every_n_create(interval_c);
- ok(policy_a != NULL,
- "Rate policy every n A created: interval: %" PRIu64,
- interval_a_b);
- ok(policy_b != NULL,
- "Rate policy every n B created: interval: %" PRIu64,
- interval_a_b);
- ok(policy_c != NULL,
- "Rate policy every n C created: interval: %" PRIu64,
- interval_c);
-
- ok(LTTNG_RATE_POLICY_TYPE_EVERY_N ==
- lttng_rate_policy_get_type(policy_a),
- "Type is LTTNG_RATE_POLICY_TYPE_EVERY_N");
-
- /* Getter tests */
- status = lttng_rate_policy_every_n_get_interval(NULL, NULL);
- ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
- "Get interval returns INVALID");
-
- status = lttng_rate_policy_every_n_get_interval(NULL, &interval_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
- "Get interval returns INVALID");
-
- status = lttng_rate_policy_every_n_get_interval(policy_a, NULL);
- ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
- "Get interval returns INVALID");
-
- status = lttng_rate_policy_every_n_get_interval(
- policy_a, &interval_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
- interval_query == interval_a_b,
- " Getting interval A");
-
- status = lttng_rate_policy_every_n_get_interval(
- policy_b, &interval_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
- interval_query == interval_a_b,
- " Getting interval B");
-
- status = lttng_rate_policy_every_n_get_interval(
- policy_c, &interval_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
- interval_query == interval_c,
- " Getting interval C");
-
- /* is_equal tests */
- /* TODO: this is the behaviour introduced by the
- * lttng_condition_is_equal back in 2017 do we want to fix this and
- * return true if both are NULL?
- */
- ok(false == lttng_rate_policy_is_equal(NULL, NULL),
- "is equal (NULL,NULL)");
- ok(false == lttng_rate_policy_is_equal(policy_a, NULL),
- "is equal (object, NULL)");
- ok(false == lttng_rate_policy_is_equal(NULL, policy_a),
- " is equal (NULL, object)");
- ok(true == lttng_rate_policy_is_equal(policy_a, policy_a),
- "is equal (object A, object A)");
-
- ok(true == lttng_rate_policy_is_equal(policy_a, policy_b),
- "is equal (object A, object B");
- ok(true == lttng_rate_policy_is_equal(policy_b, policy_a),
- "is equal (object B, object A");
-
- ok(false == lttng_rate_policy_is_equal(policy_a, policy_c),
- "is equal (object A, object C)");
- ok(false == lttng_rate_policy_is_equal(policy_c, policy_a),
- "is equal (object C, object A)");
-
- /* Serialization and create_from buffer. */
- ok(lttng_rate_policy_serialize(policy_a, &payload) == 0, "Serializing");
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_rate_policy_create_from_payload(
- &view, &policy_from_buffer) > 0 &&
- policy_from_buffer != NULL,
- "Deserializing");
- }
-
- ok(lttng_rate_policy_is_equal(policy_a, policy_from_buffer),
- "serialized and from buffer are equal");
-
- lttng_rate_policy_destroy(policy_a);
- lttng_rate_policy_destroy(policy_b);
- lttng_rate_policy_destroy(policy_c);
- lttng_payload_reset(&payload);
-}
-
-static void test_rate_policy_once_after_n(void)
-{
- enum lttng_rate_policy_status status;
- struct lttng_rate_policy *policy_a = NULL; /* Threshold of 100. */
- struct lttng_rate_policy *policy_b = NULL; /* threshold of 100 */
- struct lttng_rate_policy *policy_c = NULL; /* threshold of 1 */
- struct lttng_rate_policy *policy_from_buffer = NULL;
- uint64_t threshold_a_b = 100;
- uint64_t threshold_c = 1;
- uint64_t threshold_query = 0;
- struct lttng_payload payload;
-
- lttng_payload_init(&payload);
-
- policy_a = lttng_rate_policy_once_after_n_create(threshold_a_b);
- policy_b = lttng_rate_policy_once_after_n_create(threshold_a_b);
- policy_c = lttng_rate_policy_once_after_n_create(threshold_c);
- ok(policy_a != NULL,
- "Rate policy every n A created: threshold: %" PRIu64,
- threshold_a_b);
- ok(policy_b != NULL,
- "Rate policy every n B created: threshold: %" PRIu64,
- threshold_a_b);
- ok(policy_c != NULL,
- "Rate policy every n C created: threshold: %" PRIu64,
- threshold_c);
-
- ok(LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N ==
- lttng_rate_policy_get_type(policy_a),
- "Type is LTTNG_RATE_POLICY_TYPE_once_after_n");
-
- /* Getter tests */
- status = lttng_rate_policy_once_after_n_get_threshold(NULL, NULL);
- ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
- "Get threshold returns INVALID");
-
- status = lttng_rate_policy_once_after_n_get_threshold(
- NULL, &threshold_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
- "Get threshold returns INVALID");
-
- status = lttng_rate_policy_once_after_n_get_threshold(policy_a, NULL);
- ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
- "Get threshold returns INVALID");
-
- status = lttng_rate_policy_once_after_n_get_threshold(
- policy_a, &threshold_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
- threshold_query == threshold_a_b,
- " Getting threshold A");
-
- status = lttng_rate_policy_once_after_n_get_threshold(
- policy_b, &threshold_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
- threshold_query == threshold_a_b,
- " Getting threshold B");
-
- status = lttng_rate_policy_once_after_n_get_threshold(
- policy_c, &threshold_query);
- ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
- threshold_query == threshold_c,
- " Getting threshold C");
-
- /* is_equal tests */
- /* TODO: this is the behaviour introduced by the
- * lttng_condition_is_equal back in 2017 do we want to fix this and
- * return true if both are NULL?
- */
- ok(false == lttng_rate_policy_is_equal(NULL, NULL),
- "is equal (NULL,NULL)");
- ok(false == lttng_rate_policy_is_equal(policy_a, NULL),
- "is equal (object, NULL)");
- ok(false == lttng_rate_policy_is_equal(NULL, policy_a),
- " is equal (NULL, object)");
- ok(true == lttng_rate_policy_is_equal(policy_a, policy_a),
- "is equal (object A, object A)");
-
- ok(true == lttng_rate_policy_is_equal(policy_a, policy_b),
- "is equal (object A, object B");
- ok(true == lttng_rate_policy_is_equal(policy_b, policy_a),
- "is equal (object B, object A");
-
- ok(false == lttng_rate_policy_is_equal(policy_a, policy_c),
- "is equal (object A, object C)");
- ok(false == lttng_rate_policy_is_equal(policy_c, policy_a),
- "is equal (object C, object A)");
-
- /* Serialization and create_from buffer. */
- ok(lttng_rate_policy_serialize(policy_a, &payload) == 0, "Serializing");
- {
- struct lttng_payload_view view =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
-
- ok(lttng_rate_policy_create_from_payload(
- &view, &policy_from_buffer) > 0 &&
- policy_from_buffer != NULL,
- "Deserializing");
- }
-
- ok(lttng_rate_policy_is_equal(policy_a, policy_from_buffer),
- "serialized and from buffer are equal");
-
- lttng_rate_policy_destroy(policy_a);
- lttng_rate_policy_destroy(policy_b);
- lttng_rate_policy_destroy(policy_c);
- lttng_payload_reset(&payload);
-}
-
-int main(int argc, const char *argv[])
-{
- plan_tests(NUM_TESTS);
- test_rate_policy_every_n();
- test_rate_policy_once_after_n();
- return exit_status();
-}
--- /dev/null
+/*
+ * Unit tests for the rate policy object API.
+ *
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/action/rate-policy-internal.h>
+#include <lttng/action/rate-policy.h>
+
+/* For error.h. */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 42
+
+static void test_rate_policy_every_n(void)
+{
+ enum lttng_rate_policy_status status;
+ struct lttng_rate_policy *policy_a = NULL; /* Interval of 100. */
+ struct lttng_rate_policy *policy_b = NULL; /* Interval of 100 */
+ struct lttng_rate_policy *policy_c = NULL; /* Interval of 1 */
+ struct lttng_rate_policy *policy_from_buffer = NULL;
+ uint64_t interval_a_b = 100;
+ uint64_t interval_c = 1;
+ uint64_t interval_query = 0;
+ struct lttng_payload payload;
+
+ lttng_payload_init(&payload);
+
+ policy_a = lttng_rate_policy_every_n_create(interval_a_b);
+ policy_b = lttng_rate_policy_every_n_create(interval_a_b);
+ policy_c = lttng_rate_policy_every_n_create(interval_c);
+ ok(policy_a != NULL,
+ "Rate policy every n A created: interval: %" PRIu64,
+ interval_a_b);
+ ok(policy_b != NULL,
+ "Rate policy every n B created: interval: %" PRIu64,
+ interval_a_b);
+ ok(policy_c != NULL,
+ "Rate policy every n C created: interval: %" PRIu64,
+ interval_c);
+
+ ok(LTTNG_RATE_POLICY_TYPE_EVERY_N ==
+ lttng_rate_policy_get_type(policy_a),
+ "Type is LTTNG_RATE_POLICY_TYPE_EVERY_N");
+
+ /* Getter tests */
+ status = lttng_rate_policy_every_n_get_interval(NULL, NULL);
+ ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
+ "Get interval returns INVALID");
+
+ status = lttng_rate_policy_every_n_get_interval(NULL, &interval_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
+ "Get interval returns INVALID");
+
+ status = lttng_rate_policy_every_n_get_interval(policy_a, NULL);
+ ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
+ "Get interval returns INVALID");
+
+ status = lttng_rate_policy_every_n_get_interval(
+ policy_a, &interval_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
+ interval_query == interval_a_b,
+ " Getting interval A");
+
+ status = lttng_rate_policy_every_n_get_interval(
+ policy_b, &interval_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
+ interval_query == interval_a_b,
+ " Getting interval B");
+
+ status = lttng_rate_policy_every_n_get_interval(
+ policy_c, &interval_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
+ interval_query == interval_c,
+ " Getting interval C");
+
+ /* is_equal tests */
+ /* TODO: this is the behaviour introduced by the
+ * lttng_condition_is_equal back in 2017 do we want to fix this and
+ * return true if both are NULL?
+ */
+ ok(false == lttng_rate_policy_is_equal(NULL, NULL),
+ "is equal (NULL,NULL)");
+ ok(false == lttng_rate_policy_is_equal(policy_a, NULL),
+ "is equal (object, NULL)");
+ ok(false == lttng_rate_policy_is_equal(NULL, policy_a),
+ " is equal (NULL, object)");
+ ok(true == lttng_rate_policy_is_equal(policy_a, policy_a),
+ "is equal (object A, object A)");
+
+ ok(true == lttng_rate_policy_is_equal(policy_a, policy_b),
+ "is equal (object A, object B");
+ ok(true == lttng_rate_policy_is_equal(policy_b, policy_a),
+ "is equal (object B, object A");
+
+ ok(false == lttng_rate_policy_is_equal(policy_a, policy_c),
+ "is equal (object A, object C)");
+ ok(false == lttng_rate_policy_is_equal(policy_c, policy_a),
+ "is equal (object C, object A)");
+
+ /* Serialization and create_from buffer. */
+ ok(lttng_rate_policy_serialize(policy_a, &payload) == 0, "Serializing");
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_rate_policy_create_from_payload(
+ &view, &policy_from_buffer) > 0 &&
+ policy_from_buffer != NULL,
+ "Deserializing");
+ }
+
+ ok(lttng_rate_policy_is_equal(policy_a, policy_from_buffer),
+ "serialized and from buffer are equal");
+
+ lttng_rate_policy_destroy(policy_a);
+ lttng_rate_policy_destroy(policy_b);
+ lttng_rate_policy_destroy(policy_c);
+ lttng_payload_reset(&payload);
+}
+
+static void test_rate_policy_once_after_n(void)
+{
+ enum lttng_rate_policy_status status;
+ struct lttng_rate_policy *policy_a = NULL; /* Threshold of 100. */
+ struct lttng_rate_policy *policy_b = NULL; /* threshold of 100 */
+ struct lttng_rate_policy *policy_c = NULL; /* threshold of 1 */
+ struct lttng_rate_policy *policy_from_buffer = NULL;
+ uint64_t threshold_a_b = 100;
+ uint64_t threshold_c = 1;
+ uint64_t threshold_query = 0;
+ struct lttng_payload payload;
+
+ lttng_payload_init(&payload);
+
+ policy_a = lttng_rate_policy_once_after_n_create(threshold_a_b);
+ policy_b = lttng_rate_policy_once_after_n_create(threshold_a_b);
+ policy_c = lttng_rate_policy_once_after_n_create(threshold_c);
+ ok(policy_a != NULL,
+ "Rate policy every n A created: threshold: %" PRIu64,
+ threshold_a_b);
+ ok(policy_b != NULL,
+ "Rate policy every n B created: threshold: %" PRIu64,
+ threshold_a_b);
+ ok(policy_c != NULL,
+ "Rate policy every n C created: threshold: %" PRIu64,
+ threshold_c);
+
+ ok(LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N ==
+ lttng_rate_policy_get_type(policy_a),
+ "Type is LTTNG_RATE_POLICY_TYPE_once_after_n");
+
+ /* Getter tests */
+ status = lttng_rate_policy_once_after_n_get_threshold(NULL, NULL);
+ ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
+ "Get threshold returns INVALID");
+
+ status = lttng_rate_policy_once_after_n_get_threshold(
+ NULL, &threshold_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
+ "Get threshold returns INVALID");
+
+ status = lttng_rate_policy_once_after_n_get_threshold(policy_a, NULL);
+ ok(status == LTTNG_RATE_POLICY_STATUS_INVALID,
+ "Get threshold returns INVALID");
+
+ status = lttng_rate_policy_once_after_n_get_threshold(
+ policy_a, &threshold_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
+ threshold_query == threshold_a_b,
+ " Getting threshold A");
+
+ status = lttng_rate_policy_once_after_n_get_threshold(
+ policy_b, &threshold_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
+ threshold_query == threshold_a_b,
+ " Getting threshold B");
+
+ status = lttng_rate_policy_once_after_n_get_threshold(
+ policy_c, &threshold_query);
+ ok(status == LTTNG_RATE_POLICY_STATUS_OK &&
+ threshold_query == threshold_c,
+ " Getting threshold C");
+
+ /* is_equal tests */
+ /* TODO: this is the behaviour introduced by the
+ * lttng_condition_is_equal back in 2017 do we want to fix this and
+ * return true if both are NULL?
+ */
+ ok(false == lttng_rate_policy_is_equal(NULL, NULL),
+ "is equal (NULL,NULL)");
+ ok(false == lttng_rate_policy_is_equal(policy_a, NULL),
+ "is equal (object, NULL)");
+ ok(false == lttng_rate_policy_is_equal(NULL, policy_a),
+ " is equal (NULL, object)");
+ ok(true == lttng_rate_policy_is_equal(policy_a, policy_a),
+ "is equal (object A, object A)");
+
+ ok(true == lttng_rate_policy_is_equal(policy_a, policy_b),
+ "is equal (object A, object B");
+ ok(true == lttng_rate_policy_is_equal(policy_b, policy_a),
+ "is equal (object B, object A");
+
+ ok(false == lttng_rate_policy_is_equal(policy_a, policy_c),
+ "is equal (object A, object C)");
+ ok(false == lttng_rate_policy_is_equal(policy_c, policy_a),
+ "is equal (object C, object A)");
+
+ /* Serialization and create_from buffer. */
+ ok(lttng_rate_policy_serialize(policy_a, &payload) == 0, "Serializing");
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_rate_policy_create_from_payload(
+ &view, &policy_from_buffer) > 0 &&
+ policy_from_buffer != NULL,
+ "Deserializing");
+ }
+
+ ok(lttng_rate_policy_is_equal(policy_a, policy_from_buffer),
+ "serialized and from buffer are equal");
+
+ lttng_rate_policy_destroy(policy_a);
+ lttng_rate_policy_destroy(policy_b);
+ lttng_rate_policy_destroy(policy_c);
+ lttng_payload_reset(&payload);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_rate_policy_every_n();
+ test_rate_policy_once_after_n();
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdarg.h>
-#include <common/string-utils/string-utils.h>
-#include <tap/tap.h>
-
-/* Number of TAP tests in this file */
-#define NUM_TESTS 69
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-static void test_one_split(const char *input, char delim, int escape_delim,
- ...)
-{
- va_list vl;
- bool all_ok = true;
- struct lttng_dynamic_pointer_array strings;
- int split_ret;
- size_t i, string_count;
-
- split_ret = strutils_split(input, delim, escape_delim, &strings);
- LTTNG_ASSERT(split_ret == 0);
- va_start(vl, escape_delim);
-
- string_count = lttng_dynamic_pointer_array_get_count(&strings);
-
- for (i = 0; i < string_count; i++) {
- const char *expected_substring = va_arg(vl, const char *);
- const char *substring =
- lttng_dynamic_pointer_array_get_pointer(
- &strings, i);
-
- diag(" got `%s`, expecting `%s`", substring, expected_substring);
-
- if (!expected_substring) {
- all_ok = false;
- break;
- }
-
- if (strcmp(substring, expected_substring) != 0) {
- all_ok = false;
- break;
- }
- }
-
- lttng_dynamic_pointer_array_reset(&strings);
- va_end(vl);
- ok(all_ok, "strutils_split() produces the expected substrings: `%s` (delim. `%c`, escape `%d`)",
- input, delim, escape_delim);
-}
-
-static void test_split(void)
-{
- test_one_split("a/b/c/d/e", '/', false, "a", "b", "c", "d", "e", NULL);
- test_one_split("a/b//d/e", '/', false, "a", "b", "", "d", "e", NULL);
- test_one_split("/b/c/d/e", '/', false, "", "b", "c", "d", "e", NULL);
- test_one_split("a/b/c/d/", '/', false, "a", "b", "c", "d", "", NULL);
- test_one_split("/b/c/d/", '/', false, "", "b", "c", "d", "", NULL);
- test_one_split("", '/', false, "", NULL);
- test_one_split("/", '/', false, "", "", NULL);
- test_one_split("//", '/', false, "", "", "", NULL);
- test_one_split("hello+world", '+', false, "hello", "world", NULL);
- test_one_split("hello\\+world", '+', false, "hello\\", "world", NULL);
- test_one_split("hello\\+world", '+', true, "hello+world", NULL);
- test_one_split("hello\\++world", '+', true, "hello+", "world", NULL);
- test_one_split("hello\\\\++world", '+', true, "hello\\\\", "", "world", NULL);
- test_one_split("hello+world\\", '+', false, "hello", "world\\", NULL);
- test_one_split("hello+world\\", '+', true, "hello", "world\\", NULL);
- test_one_split("\\+", '+', false, "\\", "", NULL);
- test_one_split("\\+", '+', true, "+", NULL);
-}
-
-static void test_one_is_star_at_the_end_only_glob_pattern(const char *pattern, bool expected)
-{
- ok(strutils_is_star_at_the_end_only_glob_pattern(pattern) == expected,
- "strutils_is_star_at_the_end_only_glob_pattern() returns the expected result: `%s` -> %d",
- pattern, expected);
-}
-
-static void test_is_star_at_the_end_only_glob_pattern(void)
-{
- test_one_is_star_at_the_end_only_glob_pattern("allo*", true);
- test_one_is_star_at_the_end_only_glob_pattern("allo\\\\*", true);
- test_one_is_star_at_the_end_only_glob_pattern("allo", false);
- test_one_is_star_at_the_end_only_glob_pattern("al*lo", false);
- test_one_is_star_at_the_end_only_glob_pattern("al\\*lo", false);
- test_one_is_star_at_the_end_only_glob_pattern("*allo", false);
- test_one_is_star_at_the_end_only_glob_pattern("al*lo*", false);
- test_one_is_star_at_the_end_only_glob_pattern("allo**", false);
- test_one_is_star_at_the_end_only_glob_pattern("allo*\\*", false);
- test_one_is_star_at_the_end_only_glob_pattern("allo\\*", false);
-}
-
-static void test_one_is_star_glob_pattern(const char *pattern, bool expected)
-{
- ok(strutils_is_star_glob_pattern(pattern) == expected,
- "strutils_is_star_glob_pattern() returns the expected result: `%s` -> %d",
- pattern, expected);
-}
-
-static void test_is_star_glob_pattern(void)
-{
- test_one_is_star_glob_pattern("allo*", true);
- test_one_is_star_glob_pattern("*allo", true);
- test_one_is_star_glob_pattern("*allo*", true);
- test_one_is_star_glob_pattern("*al*lo*", true);
- test_one_is_star_glob_pattern("al\\**lo", true);
- test_one_is_star_glob_pattern("al\\*l*o", true);
- test_one_is_star_glob_pattern("all*o\\", true);
- test_one_is_star_glob_pattern("*", true);
- test_one_is_star_glob_pattern("\\\\*", true);
- test_one_is_star_glob_pattern("allo", false);
- test_one_is_star_glob_pattern("allo\\*", false);
- test_one_is_star_glob_pattern("al\\*lo", false);
- test_one_is_star_glob_pattern("\\*allo", false);
- test_one_is_star_glob_pattern("\\*", false);
- test_one_is_star_glob_pattern("allo\\", false);
-}
-
-static void test_one_normalize_star_glob_pattern(const char *pattern,
- const char *expected)
-{
- char *rw_pattern = strdup(pattern);
-
- LTTNG_ASSERT(rw_pattern);
- strutils_normalize_star_glob_pattern(rw_pattern);
- ok(strcmp(rw_pattern, expected) == 0,
- "strutils_normalize_star_glob_pattern() produces the expected result: `%s` -> `%s`",
- pattern, expected);
- free(rw_pattern);
-}
-
-static void test_normalize_star_glob_pattern(void)
-{
- test_one_normalize_star_glob_pattern("salut", "salut");
- test_one_normalize_star_glob_pattern("sal*ut", "sal*ut");
- test_one_normalize_star_glob_pattern("sal**ut", "sal*ut");
- test_one_normalize_star_glob_pattern("sal***ut", "sal*ut");
- test_one_normalize_star_glob_pattern("*salut", "*salut");
- test_one_normalize_star_glob_pattern("**salut", "*salut");
- test_one_normalize_star_glob_pattern("***salut", "*salut");
- test_one_normalize_star_glob_pattern("salut*", "salut*");
- test_one_normalize_star_glob_pattern("salut**", "salut*");
- test_one_normalize_star_glob_pattern("salut***", "salut*");
- test_one_normalize_star_glob_pattern("sa\\*lut", "sa\\*lut");
- test_one_normalize_star_glob_pattern("sa\\**lut", "sa\\**lut");
- test_one_normalize_star_glob_pattern("sa*\\**lut", "sa*\\**lut");
- test_one_normalize_star_glob_pattern("sa*\\***lut", "sa*\\**lut");
- test_one_normalize_star_glob_pattern("\\*salu**t", "\\*salu*t");
- test_one_normalize_star_glob_pattern("\\*salut**", "\\*salut*");
- test_one_normalize_star_glob_pattern("\\*salut**\\*", "\\*salut*\\*");
- test_one_normalize_star_glob_pattern("\\*salut", "\\*salut");
- test_one_normalize_star_glob_pattern("\\***salut", "\\**salut");
- test_one_normalize_star_glob_pattern("salut\\", "salut\\");
- test_one_normalize_star_glob_pattern("salut\\**", "salut\\**");
- test_one_normalize_star_glob_pattern("salut\\\\*", "salut\\\\*");
- test_one_normalize_star_glob_pattern("salut\\\\***", "salut\\\\*");
- test_one_normalize_star_glob_pattern("*", "*");
- test_one_normalize_star_glob_pattern("**", "*");
- test_one_normalize_star_glob_pattern("***", "*");
- test_one_normalize_star_glob_pattern("**\\***", "*\\**");
-}
-
-int main(int argc, char **argv)
-{
- plan_tests(NUM_TESTS);
- diag("String utils unit tests");
- test_normalize_star_glob_pattern();
- test_is_star_glob_pattern();
- test_is_star_at_the_end_only_glob_pattern();
- test_split();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdarg.h>
+#include <common/string-utils/string-utils.h>
+#include <tap/tap.h>
+
+/* Number of TAP tests in this file */
+#define NUM_TESTS 69
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+static void test_one_split(const char *input, char delim, int escape_delim,
+ ...)
+{
+ va_list vl;
+ bool all_ok = true;
+ struct lttng_dynamic_pointer_array strings;
+ int split_ret;
+ size_t i, string_count;
+
+ split_ret = strutils_split(input, delim, escape_delim, &strings);
+ LTTNG_ASSERT(split_ret == 0);
+ va_start(vl, escape_delim);
+
+ string_count = lttng_dynamic_pointer_array_get_count(&strings);
+
+ for (i = 0; i < string_count; i++) {
+ const char *expected_substring = va_arg(vl, const char *);
+ const char *substring =
+ (const char *) lttng_dynamic_pointer_array_get_pointer(
+ &strings, i);
+
+ diag(" got `%s`, expecting `%s`", substring, expected_substring);
+
+ if (!expected_substring) {
+ all_ok = false;
+ break;
+ }
+
+ if (strcmp(substring, expected_substring) != 0) {
+ all_ok = false;
+ break;
+ }
+ }
+
+ lttng_dynamic_pointer_array_reset(&strings);
+ va_end(vl);
+ ok(all_ok, "strutils_split() produces the expected substrings: `%s` (delim. `%c`, escape `%d`)",
+ input, delim, escape_delim);
+}
+
+static void test_split(void)
+{
+ test_one_split("a/b/c/d/e", '/', false, "a", "b", "c", "d", "e", NULL);
+ test_one_split("a/b//d/e", '/', false, "a", "b", "", "d", "e", NULL);
+ test_one_split("/b/c/d/e", '/', false, "", "b", "c", "d", "e", NULL);
+ test_one_split("a/b/c/d/", '/', false, "a", "b", "c", "d", "", NULL);
+ test_one_split("/b/c/d/", '/', false, "", "b", "c", "d", "", NULL);
+ test_one_split("", '/', false, "", NULL);
+ test_one_split("/", '/', false, "", "", NULL);
+ test_one_split("//", '/', false, "", "", "", NULL);
+ test_one_split("hello+world", '+', false, "hello", "world", NULL);
+ test_one_split("hello\\+world", '+', false, "hello\\", "world", NULL);
+ test_one_split("hello\\+world", '+', true, "hello+world", NULL);
+ test_one_split("hello\\++world", '+', true, "hello+", "world", NULL);
+ test_one_split("hello\\\\++world", '+', true, "hello\\\\", "", "world", NULL);
+ test_one_split("hello+world\\", '+', false, "hello", "world\\", NULL);
+ test_one_split("hello+world\\", '+', true, "hello", "world\\", NULL);
+ test_one_split("\\+", '+', false, "\\", "", NULL);
+ test_one_split("\\+", '+', true, "+", NULL);
+}
+
+static void test_one_is_star_at_the_end_only_glob_pattern(const char *pattern, bool expected)
+{
+ ok(strutils_is_star_at_the_end_only_glob_pattern(pattern) == expected,
+ "strutils_is_star_at_the_end_only_glob_pattern() returns the expected result: `%s` -> %d",
+ pattern, expected);
+}
+
+static void test_is_star_at_the_end_only_glob_pattern(void)
+{
+ test_one_is_star_at_the_end_only_glob_pattern("allo*", true);
+ test_one_is_star_at_the_end_only_glob_pattern("allo\\\\*", true);
+ test_one_is_star_at_the_end_only_glob_pattern("allo", false);
+ test_one_is_star_at_the_end_only_glob_pattern("al*lo", false);
+ test_one_is_star_at_the_end_only_glob_pattern("al\\*lo", false);
+ test_one_is_star_at_the_end_only_glob_pattern("*allo", false);
+ test_one_is_star_at_the_end_only_glob_pattern("al*lo*", false);
+ test_one_is_star_at_the_end_only_glob_pattern("allo**", false);
+ test_one_is_star_at_the_end_only_glob_pattern("allo*\\*", false);
+ test_one_is_star_at_the_end_only_glob_pattern("allo\\*", false);
+}
+
+static void test_one_is_star_glob_pattern(const char *pattern, bool expected)
+{
+ ok(strutils_is_star_glob_pattern(pattern) == expected,
+ "strutils_is_star_glob_pattern() returns the expected result: `%s` -> %d",
+ pattern, expected);
+}
+
+static void test_is_star_glob_pattern(void)
+{
+ test_one_is_star_glob_pattern("allo*", true);
+ test_one_is_star_glob_pattern("*allo", true);
+ test_one_is_star_glob_pattern("*allo*", true);
+ test_one_is_star_glob_pattern("*al*lo*", true);
+ test_one_is_star_glob_pattern("al\\**lo", true);
+ test_one_is_star_glob_pattern("al\\*l*o", true);
+ test_one_is_star_glob_pattern("all*o\\", true);
+ test_one_is_star_glob_pattern("*", true);
+ test_one_is_star_glob_pattern("\\\\*", true);
+ test_one_is_star_glob_pattern("allo", false);
+ test_one_is_star_glob_pattern("allo\\*", false);
+ test_one_is_star_glob_pattern("al\\*lo", false);
+ test_one_is_star_glob_pattern("\\*allo", false);
+ test_one_is_star_glob_pattern("\\*", false);
+ test_one_is_star_glob_pattern("allo\\", false);
+}
+
+static void test_one_normalize_star_glob_pattern(const char *pattern,
+ const char *expected)
+{
+ char *rw_pattern = strdup(pattern);
+
+ LTTNG_ASSERT(rw_pattern);
+ strutils_normalize_star_glob_pattern(rw_pattern);
+ ok(strcmp(rw_pattern, expected) == 0,
+ "strutils_normalize_star_glob_pattern() produces the expected result: `%s` -> `%s`",
+ pattern, expected);
+ free(rw_pattern);
+}
+
+static void test_normalize_star_glob_pattern(void)
+{
+ test_one_normalize_star_glob_pattern("salut", "salut");
+ test_one_normalize_star_glob_pattern("sal*ut", "sal*ut");
+ test_one_normalize_star_glob_pattern("sal**ut", "sal*ut");
+ test_one_normalize_star_glob_pattern("sal***ut", "sal*ut");
+ test_one_normalize_star_glob_pattern("*salut", "*salut");
+ test_one_normalize_star_glob_pattern("**salut", "*salut");
+ test_one_normalize_star_glob_pattern("***salut", "*salut");
+ test_one_normalize_star_glob_pattern("salut*", "salut*");
+ test_one_normalize_star_glob_pattern("salut**", "salut*");
+ test_one_normalize_star_glob_pattern("salut***", "salut*");
+ test_one_normalize_star_glob_pattern("sa\\*lut", "sa\\*lut");
+ test_one_normalize_star_glob_pattern("sa\\**lut", "sa\\**lut");
+ test_one_normalize_star_glob_pattern("sa*\\**lut", "sa*\\**lut");
+ test_one_normalize_star_glob_pattern("sa*\\***lut", "sa*\\**lut");
+ test_one_normalize_star_glob_pattern("\\*salu**t", "\\*salu*t");
+ test_one_normalize_star_glob_pattern("\\*salut**", "\\*salut*");
+ test_one_normalize_star_glob_pattern("\\*salut**\\*", "\\*salut*\\*");
+ test_one_normalize_star_glob_pattern("\\*salut", "\\*salut");
+ test_one_normalize_star_glob_pattern("\\***salut", "\\**salut");
+ test_one_normalize_star_glob_pattern("salut\\", "salut\\");
+ test_one_normalize_star_glob_pattern("salut\\**", "salut\\**");
+ test_one_normalize_star_glob_pattern("salut\\\\*", "salut\\\\*");
+ test_one_normalize_star_glob_pattern("salut\\\\***", "salut\\\\*");
+ test_one_normalize_star_glob_pattern("*", "*");
+ test_one_normalize_star_glob_pattern("**", "*");
+ test_one_normalize_star_glob_pattern("***", "*");
+ test_one_normalize_star_glob_pattern("**\\***", "*\\**");
+}
+
+int main(int argc, char **argv)
+{
+ plan_tests(NUM_TESTS);
+ diag("String utils unit tests");
+ test_normalize_star_glob_pattern();
+ test_is_star_glob_pattern();
+ test_is_star_at_the_end_only_glob_pattern();
+ test_split();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <common/compat/fcntl.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-#include <common/unix.h>
-#include <common/utils.h>
-#include <common/defaults.h>
-#include <tap/tap.h>
-#include <stdbool.h>
-#include <common/error.h>
-#include <lttng/constant.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-
-#define HIGH_FD_COUNT LTTCOMM_MAX_SEND_FDS
-#define MESSAGE_COUNT 4
-#define LARGE_PAYLOAD_SIZE 4 * 1024
-#define LARGE_PAYLOAD_RECV_SIZE 100
-
-static const int TEST_COUNT = 37;
-
-/* For error.h */
-int lttng_opt_quiet;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-/*
- * Validate that a large number of file descriptors can be received in one shot.
- */
-static void test_high_fd_count(unsigned int fd_count)
-{
- int sockets[2] = {-1, -1};
- int ret;
- unsigned int i;
- const unsigned int payload_content = 42;
- struct lttng_payload sent_payload;
- struct lttng_payload received_payload;
-
- diag("Send and receive high FD count atomically (%u FDs)", fd_count);
- lttng_payload_init(&sent_payload);
- lttng_payload_init(&received_payload);
-
- ret = lttcomm_create_anon_unix_socketpair(sockets);
- ok(ret == 0, "Created anonymous unix socket pair");
- if (ret < 0) {
- PERROR("Failed to create an anonymous pair of unix sockets");
- goto error;
- }
-
- /* Add dummy content to payload. */
- ret = lttng_dynamic_buffer_append(&sent_payload.buffer,
- &payload_content, sizeof(payload_content));
- if (ret) {
- PERROR("Failed to initialize test payload");
- goto error;
- }
-
- for (i = 0; i < fd_count; i++) {
- struct fd_handle *handle;
- int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
-
- if (fd < 0) {
- PERROR("Failed to create fd while creating test payload");
- goto error;
- }
-
- handle = fd_handle_create(fd);
- if (!handle) {
- if (close(fd)) {
- PERROR("Failed to close fd while preparing test payload");
- goto error;
- }
- }
-
- ret = lttng_payload_push_fd_handle(&sent_payload, handle);
- fd_handle_put(handle);
- if (ret) {
- PERROR("Failed to add fd handle to test payload");
- goto error;
- }
- }
-
- /* Send payload. */
- {
- ssize_t sock_ret;
- struct lttng_payload_view pv = lttng_payload_view_from_payload(
- &sent_payload, 0, -1);
-
- /* Not expected to block considering the size of the payload. */
- sock_ret = lttcomm_send_unix_sock(
- sockets[0], pv.buffer.data, pv.buffer.size);
- ok(sock_ret == pv.buffer.size, "Sent complete test payload");
- if (sock_ret != pv.buffer.size) {
- ERR("Failed to send test payload bytes: ret = %zd, expected = %zu",
- sock_ret, pv.buffer.size);
- goto error;
- }
-
- sock_ret = lttcomm_send_payload_view_fds_unix_sock(
- sockets[0], &pv);
- ok(sock_ret == 1, "Sent test payload file descriptors");
- if (sock_ret != 1) {
- if (sock_ret < 0) {
- PERROR("Failed to send test payload file descriptors: ret = %zd, expected = %d",
- sock_ret, 1);
- } else {
- diag("Failed to send test payload file descriptors: ret = %zd, expected = %d",
- sock_ret, 1);
- }
-
- goto error;
- }
- }
-
- /* Receive payload */
- {
- ssize_t sock_ret;
-
- ret = lttng_dynamic_buffer_set_size(&received_payload.buffer,
- sent_payload.buffer.size);
- if (ret) {
- PERROR("Failed to pre-allocate reception buffer");
- goto error;
- }
-
- sock_ret = lttcomm_recv_unix_sock(sockets[1],
- received_payload.buffer.data,
- received_payload.buffer.size);
- ok(sock_ret == received_payload.buffer.size,
- "Received payload bytes");
- if (sock_ret != received_payload.buffer.size) {
- ERR("Failed to receive payload bytes: ret = %zd, expected = %zu",
- sock_ret, received_payload.buffer.size);
- goto error;
- }
-
- sock_ret = lttcomm_recv_payload_fds_unix_sock(
- sockets[1], fd_count, &received_payload);
- ok(sock_ret == (int) (sizeof(int) * fd_count),
- "FD reception return value is number of fd * sizeof(int)");
- if (sock_ret != (int) (sizeof(int) * fd_count)) {
- ERR("Failed to receive test payload file descriptors: ret = %zd, expected = %d",
- sock_ret,
- (int) (fd_count * sizeof(int)));
- goto error;
- }
-
- {
- const struct lttng_payload_view pv =
- lttng_payload_view_from_payload(
- &received_payload, 0,
- -1);
- const int fd_handle_count =
- lttng_payload_view_get_fd_handle_count(
- &pv);
-
- ok(fd_handle_count == fd_count,
- "Received all test payload file descriptors in one invocation");
- }
- }
-
-error:
- for (i = 0; i < 2; i++) {
- if (sockets[i] < 0) {
- continue;
- }
-
- if (close(sockets[i])) {
- PERROR("Failed to close unix socket");
- }
- }
-
- lttng_payload_reset(&sent_payload);
- lttng_payload_reset(&received_payload);
-}
-
-/*
- * Validate that if the sender sent multiple messages, each containing 1 fd,
- * the receiver can receive one message at a time (the binary payload and its
- * fd) and is not forced to receive all file descriptors at once.
- */
-static void test_one_fd_per_message(unsigned int message_count)
-{
- const unsigned int payload_content = 42;
- int sockets[2] = {-1, -1};
- int ret;
- unsigned int i;
- struct lttng_payload sent_payload;
- struct lttng_payload received_payload;
-
- diag("Send and receive small messages with one FD each (%u messages)",
- message_count);
- lttng_payload_init(&sent_payload);
- lttng_payload_init(&received_payload);
-
- ret = lttcomm_create_anon_unix_socketpair(sockets);
- ok(ret == 0, "Created anonymous unix socket pair");
- if (ret < 0) {
- PERROR("Failed to create an anonymous pair of unix sockets");
- goto error;
- }
-
- /* Send messages with one fd each. */
- for (i = 0; i < message_count; i++) {
- struct fd_handle *handle;
- int fd;
-
- /* Add dummy content to payload. */
- ret = lttng_dynamic_buffer_append(&sent_payload.buffer,
- &payload_content, sizeof(payload_content));
- if (ret) {
- PERROR("Failed to initialize test payload");
- goto error;
- }
-
- fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
- if (fd < 0) {
- PERROR("Failed to create fd while creating test payload");
- goto error;
- }
-
- handle = fd_handle_create(fd);
- if (!handle) {
- if (close(fd)) {
- PERROR("Failed to close fd while preparing test payload");
- goto error;
- }
- }
-
- ret = lttng_payload_push_fd_handle(&sent_payload, handle);
- fd_handle_put(handle);
- if (ret) {
- PERROR("Failed to add fd handle to test payload");
- goto error;
- }
-
- /* Send payload. */
- {
- ssize_t sock_ret;
- struct lttng_payload_view pv =
- lttng_payload_view_from_payload(
- &sent_payload, 0, -1);
-
- /* Not expected to block considering the size of the
- * payload. */
- sock_ret = lttcomm_send_unix_sock(sockets[0],
- pv.buffer.data, pv.buffer.size);
- ok(sock_ret == pv.buffer.size,
- "Sent binary payload for message %u",
- i);
- if (sock_ret != pv.buffer.size) {
- ERR("Failed to send test payload bytes: ret = %zd, expected = %zu",
- sock_ret, pv.buffer.size);
- goto error;
- }
-
- sock_ret = lttcomm_send_payload_view_fds_unix_sock(
- sockets[0], &pv);
- ok(sock_ret == 1,
- "Sent file descriptors payload for message %u",
- i);
- if (sock_ret != 1) {
- if (sock_ret < 0) {
- PERROR("Failed to send test payload file descriptors: ret = %zd, expected = %d",
- sock_ret, 1);
- } else {
- diag("Failed to send test payload file descriptors: ret = %zd, expected = %d",
- sock_ret, 1);
- }
-
- goto error;
- }
- }
-
- lttng_payload_clear(&sent_payload);
- }
-
- /* Receive messages one at a time. */
- for (i = 0; i < message_count; i++) {
- ssize_t sock_ret;
-
- ret = lttng_dynamic_buffer_set_size(&received_payload.buffer,
- sizeof(payload_content));
- if (ret) {
- PERROR("Failed to pre-allocate reception buffer");
- goto error;
- }
-
- sock_ret = lttcomm_recv_unix_sock(sockets[1],
- received_payload.buffer.data,
- received_payload.buffer.size);
- ok(sock_ret == received_payload.buffer.size,
- "Received payload bytes for message %u", i);
- if (sock_ret != received_payload.buffer.size) {
- ERR("Failed to receive payload bytes: ret = %zd, expected = %zu",
- sock_ret, received_payload.buffer.size);
- goto error;
- }
-
- sock_ret = lttcomm_recv_payload_fds_unix_sock(
- sockets[1], 1, &received_payload);
- ok(sock_ret == (int) sizeof(int), "Received fd for message %u",
- i);
- if (sock_ret != (int) sizeof(int)) {
- ERR("Failed to receive test payload file descriptors: ret = %zd, expected = %u",
- sock_ret, (int) sizeof(int));
- goto error;
- }
-
- {
- const struct lttng_payload_view pv =
- lttng_payload_view_from_payload(
- &received_payload, 0,
- -1);
- const int fd_handle_count =
- lttng_payload_view_get_fd_handle_count(
- &pv);
-
- ok(fd_handle_count == 1,
- "Payload contains 1 fd for message %u",
- i);
- }
-
- lttng_payload_clear(&received_payload);
- }
-
-error:
- for (i = 0; i < 2; i++) {
- if (sockets[i] < 0) {
- continue;
- }
-
- if (close(sockets[i])) {
- PERROR("Failed to close unix socket");
- }
- }
-
- lttng_payload_reset(&sent_payload);
- lttng_payload_reset(&received_payload);
-}
-
-/*
- * Validate that a large message can be received in multiple chunks.
- */
-static void test_receive_in_chunks(
- unsigned int payload_size, unsigned int max_recv_size)
-{
- int sockets[2] = {-1, -1};
- int ret;
- unsigned int i;
- struct lttng_payload sent_payload;
- struct lttng_payload received_payload;
- struct fd_handle *handle;
- int fd;
- ssize_t sock_ret, received = 0;
-
- diag("Receive a message in multiple chunks");
- lttng_payload_init(&sent_payload);
- lttng_payload_init(&received_payload);
-
- ret = lttcomm_create_anon_unix_socketpair(sockets);
- ok(ret == 0, "Created anonymous unix socket pair");
- if (ret < 0) {
- PERROR("Failed to create an anonymous pair of unix sockets");
- goto error;
- }
-
- /* Add dummy content to payload. */
- ret = lttng_dynamic_buffer_set_size(&sent_payload.buffer, payload_size);
- if (ret) {
- PERROR("Failed to initialize test payload");
- goto error;
- }
-
- fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
- if (fd < 0) {
- PERROR("Failed to create fd while creating test payload");
- goto error;
- }
-
- handle = fd_handle_create(fd);
- if (!handle) {
- if (close(fd)) {
- PERROR("Failed to close fd while preparing test payload");
- goto error;
- }
- }
-
- ret = lttng_payload_push_fd_handle(&sent_payload, handle);
- fd_handle_put(handle);
- if (ret) {
- PERROR("Failed to add fd handle to test payload");
- goto error;
- }
-
- /* Send payload. */
- {
- struct lttng_payload_view pv = lttng_payload_view_from_payload(
- &sent_payload, 0, -1);
-
- /* Not expected to block considering the size of the payload. */
- sock_ret = lttcomm_send_unix_sock(
- sockets[0], pv.buffer.data, pv.buffer.size);
- ok(sock_ret == pv.buffer.size, "Sent complete test payload");
- if (sock_ret != pv.buffer.size) {
- ERR("Failed to send test payload bytes: ret = %zd, expected = %zu",
- sock_ret, pv.buffer.size);
- goto error;
- }
-
- sock_ret = lttcomm_send_payload_view_fds_unix_sock(
- sockets[0], &pv);
- ok(sock_ret == 1, "Sent test payload file descriptors");
- if (sock_ret != 1) {
- if (sock_ret < 0) {
- PERROR("Failed to send test payload file descriptors: ret = %zd, expected = %d",
- sock_ret, 1);
- } else {
- diag("Failed to send test payload file descriptors: ret = %zd, expected = %d",
- sock_ret, 1);
- }
-
- goto error;
- }
- }
-
- /* Receive payload */
- ret = lttng_dynamic_buffer_set_size(
- &received_payload.buffer, sent_payload.buffer.size);
- if (ret) {
- PERROR("Failed to pre-allocate reception buffer");
- goto error;
- }
-
- do {
- const ssize_t to_receive_this_pass = min(max_recv_size,
- sent_payload.buffer.size - received);
-
- sock_ret = lttcomm_recv_unix_sock(sockets[1],
- received_payload.buffer.data + received,
- to_receive_this_pass);
- if (sock_ret != to_receive_this_pass) {
- ERR("Failed to receive payload bytes: ret = %zd, expected = %zu",
- sock_ret, to_receive_this_pass);
- break;
- }
-
- received += sock_ret;
- } while (received < sent_payload.buffer.size);
-
- ok(received == sent_payload.buffer.size,
- "Received complete payload in chunks of %u bytes",
- max_recv_size);
- if (received != sent_payload.buffer.size) {
- goto error;
- }
-
- sock_ret = lttcomm_recv_payload_fds_unix_sock(
- sockets[1], 1, &received_payload);
- ok(sock_ret == (int) sizeof(int),
- "Received file descriptor after receiving payload in chunks");
- if (sock_ret != (int) sizeof(int)) {
- ERR("Failed to receive test payload file descriptors: ret = %zd, expected = %d",
- sock_ret, (int) sizeof(int));
- goto error;
- }
-
- {
- const struct lttng_payload_view pv =
- lttng_payload_view_from_payload(
- &received_payload, 0, -1);
- const int fd_handle_count =
- lttng_payload_view_get_fd_handle_count(&pv);
-
- ok(fd_handle_count == 1,
- "Payload contains 1 fd after receiving payload in chunks");
- }
-
-error:
- for (i = 0; i < 2; i++) {
- if (sockets[i] < 0) {
- continue;
- }
-
- if (close(sockets[i])) {
- PERROR("Failed to close unix socket");
- }
- }
-
- lttng_payload_reset(&sent_payload);
- lttng_payload_reset(&received_payload);
-}
-
-static
-void test_creds_passing(void)
-{
- pid_t fork_ret = -1;
- int ret, parent_socket = -1, child_connection_socket = -1;
- ssize_t sock_ret;
- char socket_dir_path[] = "/tmp/test.unix.socket.creds.passing.XXXXXX";
- char socket_path[PATH_MAX] = {};
- struct expected_creds {
- uid_t euid;
- gid_t egid;
- pid_t pid;
- } expected_creds;
-
- diag("Receive peer's effective uid, effective gid, and pid from a unix socket");
-
- if (!mkdtemp(socket_dir_path)) {
- PERROR("Failed to generate temporary socket location");
- goto error;
- }
-
- strncat(socket_path, socket_dir_path,
- sizeof(socket_path) - strlen(socket_path) - 1);
- strncat(socket_path, "/test_unix_socket",
- sizeof(socket_path) - strlen(socket_path) - 1);
-
- parent_socket = lttcomm_create_unix_sock(socket_path);
- ok(parent_socket >= 0, "Created unix socket at path `%s`", socket_path);
- if (parent_socket < 0) {
- PERROR("Failed to create unix socket at path `%s`", socket_path);
- goto error;
- }
-
- ret = lttcomm_listen_unix_sock(parent_socket);
- if (ret < 0) {
- PERROR("Failed to mark parent socket as a passive socket");
- goto error;
- }
-
- ret = lttcomm_setsockopt_creds_unix_sock(parent_socket);
- if (ret) {
- PERROR("Failed to set SO_PASSCRED on parent socket");
- goto error;
- }
-
- fork_ret = fork();
- if (fork_ret < 0) {
- PERROR("Failed to fork");
- goto error;
- }
-
- if (fork_ret == 0) {
- /* Child. */
- int child_socket;
-
- expected_creds = (struct expected_creds){
- .euid = geteuid(),
- .egid = getegid(),
- .pid = getpid(),
- };
-
- child_socket = lttcomm_connect_unix_sock(socket_path);
- if (child_socket < 0) {
- PERROR("Failed to connect to parent socket");
- goto error;
- }
-
- ret = lttcomm_setsockopt_creds_unix_sock(child_socket);
- if (ret) {
- PERROR("Failed to set SO_PASSCRED on child socket");
- }
-
- sock_ret = lttcomm_send_creds_unix_sock(child_socket, &expected_creds,
- sizeof(expected_creds));
- if (sock_ret < 0) {
- PERROR("Failed to send expected credentials");
- }
-
- ret = close(child_socket);
- if (ret) {
- PERROR("Failed to close child socket");
- }
- } else {
- /* Parent. */
- int child_status;
- pid_t wait_pid_ret;
- lttng_sock_cred received_creds = {};
-
- child_connection_socket =
- lttcomm_accept_unix_sock(parent_socket);
- if (child_connection_socket < 0) {
- PERROR();
- goto error;
- }
-
- ret = lttcomm_setsockopt_creds_unix_sock(
- child_connection_socket);
- if (ret) {
- PERROR("Failed to set SO_PASSCRED on child connection socket");
- goto error;
- }
-
- sock_ret = lttcomm_recv_creds_unix_sock(child_connection_socket,
- &expected_creds, sizeof(expected_creds),
- &received_creds);
- if (sock_ret < 0) {
- PERROR("Failed to receive credentials");
- goto error;
- }
-
- wait_pid_ret = waitpid(fork_ret, &child_status, 0);
- if (wait_pid_ret == -1) {
- PERROR("Failed to wait for termination of child process");
- goto error;
- }
- if (!WIFEXITED(child_status) || WEXITSTATUS(child_status)) {
- diag("Child process reported an error, test failed");
- goto error;
- }
-
- ok(expected_creds.euid == received_creds.uid,
- "Received the expected effective uid (%d == %d)",
- expected_creds.euid, received_creds.uid);
- ok(expected_creds.egid == received_creds.gid,
- "Received the expected effective gid (%d == %d)",
- expected_creds.egid, received_creds.gid);
- ok(expected_creds.pid == received_creds.pid,
- "Received the expected pid (%d == %d)",
- expected_creds.pid, received_creds.pid);
- }
-
-error:
- if (parent_socket >= 0) {
- ret = close(parent_socket);
- if (ret) {
- PERROR("Failed to close parent socket");
- }
- }
-
- if (fork_ret == 0) {
- /* Prevent libtap from printing a result for the child. */
- fclose(stdout);
- fclose(stderr);
-
- /* Child exits at the end of this test. */
- exit(0);
- } else if (parent_socket >= 0) {
- if (child_connection_socket >= 0) {
- ret = close(child_connection_socket);
- if (ret) {
- PERROR("Failed to close child connection socket");
- }
- }
-
- ret = unlink(socket_path);
- if (ret) {
- PERROR("Failed to unlink socket at path `%s`",
- socket_path);
- }
-
- ret = rmdir(socket_dir_path);
- if (ret) {
- PERROR("Failed to remove test directory at `%s`",
- socket_dir_path);
- }
- }
-}
-
-int main(void)
-{
- plan_tests(TEST_COUNT);
-
- test_high_fd_count(HIGH_FD_COUNT);
- test_one_fd_per_message(MESSAGE_COUNT);
- test_receive_in_chunks(LARGE_PAYLOAD_SIZE, LARGE_PAYLOAD_RECV_SIZE);
- test_creds_passing();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <algorithm>
+#include <common/compat/fcntl.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/payload.h>
+#include <common/payload-view.h>
+#include <common/unix.h>
+#include <common/utils.h>
+#include <common/defaults.h>
+#include <tap/tap.h>
+#include <stdbool.h>
+#include <common/error.h>
+#include <lttng/constant.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#define HIGH_FD_COUNT LTTCOMM_MAX_SEND_FDS
+#define MESSAGE_COUNT 4
+#define LARGE_PAYLOAD_SIZE 4 * 1024
+#define LARGE_PAYLOAD_RECV_SIZE 100
+
+static const int TEST_COUNT = 37;
+
+/* For error.h */
+int lttng_opt_quiet;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+/*
+ * Validate that a large number of file descriptors can be received in one shot.
+ */
+static void test_high_fd_count(unsigned int fd_count)
+{
+ int sockets[2] = {-1, -1};
+ int ret;
+ unsigned int i;
+ const unsigned int payload_content = 42;
+ struct lttng_payload sent_payload;
+ struct lttng_payload received_payload;
+
+ diag("Send and receive high FD count atomically (%u FDs)", fd_count);
+ lttng_payload_init(&sent_payload);
+ lttng_payload_init(&received_payload);
+
+ ret = lttcomm_create_anon_unix_socketpair(sockets);
+ ok(ret == 0, "Created anonymous unix socket pair");
+ if (ret < 0) {
+ PERROR("Failed to create an anonymous pair of unix sockets");
+ goto error;
+ }
+
+ /* Add dummy content to payload. */
+ ret = lttng_dynamic_buffer_append(&sent_payload.buffer,
+ &payload_content, sizeof(payload_content));
+ if (ret) {
+ PERROR("Failed to initialize test payload");
+ goto error;
+ }
+
+ for (i = 0; i < fd_count; i++) {
+ struct fd_handle *handle;
+ int fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
+
+ if (fd < 0) {
+ PERROR("Failed to create fd while creating test payload");
+ goto error;
+ }
+
+ handle = fd_handle_create(fd);
+ if (!handle) {
+ if (close(fd)) {
+ PERROR("Failed to close fd while preparing test payload");
+ goto error;
+ }
+ }
+
+ ret = lttng_payload_push_fd_handle(&sent_payload, handle);
+ fd_handle_put(handle);
+ if (ret) {
+ PERROR("Failed to add fd handle to test payload");
+ goto error;
+ }
+ }
+
+ /* Send payload. */
+ {
+ ssize_t sock_ret;
+ struct lttng_payload_view pv = lttng_payload_view_from_payload(
+ &sent_payload, 0, -1);
+
+ /* Not expected to block considering the size of the payload. */
+ sock_ret = lttcomm_send_unix_sock(
+ sockets[0], pv.buffer.data, pv.buffer.size);
+ ok(sock_ret == pv.buffer.size, "Sent complete test payload");
+ if (sock_ret != pv.buffer.size) {
+ ERR("Failed to send test payload bytes: ret = %zd, expected = %zu",
+ sock_ret, pv.buffer.size);
+ goto error;
+ }
+
+ sock_ret = lttcomm_send_payload_view_fds_unix_sock(
+ sockets[0], &pv);
+ ok(sock_ret == 1, "Sent test payload file descriptors");
+ if (sock_ret != 1) {
+ if (sock_ret < 0) {
+ PERROR("Failed to send test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret, 1);
+ } else {
+ diag("Failed to send test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret, 1);
+ }
+
+ goto error;
+ }
+ }
+
+ /* Receive payload */
+ {
+ ssize_t sock_ret;
+
+ ret = lttng_dynamic_buffer_set_size(&received_payload.buffer,
+ sent_payload.buffer.size);
+ if (ret) {
+ PERROR("Failed to pre-allocate reception buffer");
+ goto error;
+ }
+
+ sock_ret = lttcomm_recv_unix_sock(sockets[1],
+ received_payload.buffer.data,
+ received_payload.buffer.size);
+ ok(sock_ret == received_payload.buffer.size,
+ "Received payload bytes");
+ if (sock_ret != received_payload.buffer.size) {
+ ERR("Failed to receive payload bytes: ret = %zd, expected = %zu",
+ sock_ret, received_payload.buffer.size);
+ goto error;
+ }
+
+ sock_ret = lttcomm_recv_payload_fds_unix_sock(
+ sockets[1], fd_count, &received_payload);
+ ok(sock_ret == (int) (sizeof(int) * fd_count),
+ "FD reception return value is number of fd * sizeof(int)");
+ if (sock_ret != (int) (sizeof(int) * fd_count)) {
+ ERR("Failed to receive test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret,
+ (int) (fd_count * sizeof(int)));
+ goto error;
+ }
+
+ {
+ const struct lttng_payload_view pv =
+ lttng_payload_view_from_payload(
+ &received_payload, 0,
+ -1);
+ const int fd_handle_count =
+ lttng_payload_view_get_fd_handle_count(
+ &pv);
+
+ ok(fd_handle_count == fd_count,
+ "Received all test payload file descriptors in one invocation");
+ }
+ }
+
+error:
+ for (i = 0; i < 2; i++) {
+ if (sockets[i] < 0) {
+ continue;
+ }
+
+ if (close(sockets[i])) {
+ PERROR("Failed to close unix socket");
+ }
+ }
+
+ lttng_payload_reset(&sent_payload);
+ lttng_payload_reset(&received_payload);
+}
+
+/*
+ * Validate that if the sender sent multiple messages, each containing 1 fd,
+ * the receiver can receive one message at a time (the binary payload and its
+ * fd) and is not forced to receive all file descriptors at once.
+ */
+static void test_one_fd_per_message(unsigned int message_count)
+{
+ const unsigned int payload_content = 42;
+ int sockets[2] = {-1, -1};
+ int ret;
+ unsigned int i;
+ struct lttng_payload sent_payload;
+ struct lttng_payload received_payload;
+
+ diag("Send and receive small messages with one FD each (%u messages)",
+ message_count);
+ lttng_payload_init(&sent_payload);
+ lttng_payload_init(&received_payload);
+
+ ret = lttcomm_create_anon_unix_socketpair(sockets);
+ ok(ret == 0, "Created anonymous unix socket pair");
+ if (ret < 0) {
+ PERROR("Failed to create an anonymous pair of unix sockets");
+ goto error;
+ }
+
+ /* Send messages with one fd each. */
+ for (i = 0; i < message_count; i++) {
+ struct fd_handle *handle;
+ int fd;
+
+ /* Add dummy content to payload. */
+ ret = lttng_dynamic_buffer_append(&sent_payload.buffer,
+ &payload_content, sizeof(payload_content));
+ if (ret) {
+ PERROR("Failed to initialize test payload");
+ goto error;
+ }
+
+ fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
+ if (fd < 0) {
+ PERROR("Failed to create fd while creating test payload");
+ goto error;
+ }
+
+ handle = fd_handle_create(fd);
+ if (!handle) {
+ if (close(fd)) {
+ PERROR("Failed to close fd while preparing test payload");
+ goto error;
+ }
+ }
+
+ ret = lttng_payload_push_fd_handle(&sent_payload, handle);
+ fd_handle_put(handle);
+ if (ret) {
+ PERROR("Failed to add fd handle to test payload");
+ goto error;
+ }
+
+ /* Send payload. */
+ {
+ ssize_t sock_ret;
+ struct lttng_payload_view pv =
+ lttng_payload_view_from_payload(
+ &sent_payload, 0, -1);
+
+ /* Not expected to block considering the size of the
+ * payload. */
+ sock_ret = lttcomm_send_unix_sock(sockets[0],
+ pv.buffer.data, pv.buffer.size);
+ ok(sock_ret == pv.buffer.size,
+ "Sent binary payload for message %u",
+ i);
+ if (sock_ret != pv.buffer.size) {
+ ERR("Failed to send test payload bytes: ret = %zd, expected = %zu",
+ sock_ret, pv.buffer.size);
+ goto error;
+ }
+
+ sock_ret = lttcomm_send_payload_view_fds_unix_sock(
+ sockets[0], &pv);
+ ok(sock_ret == 1,
+ "Sent file descriptors payload for message %u",
+ i);
+ if (sock_ret != 1) {
+ if (sock_ret < 0) {
+ PERROR("Failed to send test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret, 1);
+ } else {
+ diag("Failed to send test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret, 1);
+ }
+
+ goto error;
+ }
+ }
+
+ lttng_payload_clear(&sent_payload);
+ }
+
+ /* Receive messages one at a time. */
+ for (i = 0; i < message_count; i++) {
+ ssize_t sock_ret;
+
+ ret = lttng_dynamic_buffer_set_size(&received_payload.buffer,
+ sizeof(payload_content));
+ if (ret) {
+ PERROR("Failed to pre-allocate reception buffer");
+ goto error;
+ }
+
+ sock_ret = lttcomm_recv_unix_sock(sockets[1],
+ received_payload.buffer.data,
+ received_payload.buffer.size);
+ ok(sock_ret == received_payload.buffer.size,
+ "Received payload bytes for message %u", i);
+ if (sock_ret != received_payload.buffer.size) {
+ ERR("Failed to receive payload bytes: ret = %zd, expected = %zu",
+ sock_ret, received_payload.buffer.size);
+ goto error;
+ }
+
+ sock_ret = lttcomm_recv_payload_fds_unix_sock(
+ sockets[1], 1, &received_payload);
+ ok(sock_ret == (int) sizeof(int), "Received fd for message %u",
+ i);
+ if (sock_ret != (int) sizeof(int)) {
+ ERR("Failed to receive test payload file descriptors: ret = %zd, expected = %u",
+ sock_ret, (int) sizeof(int));
+ goto error;
+ }
+
+ {
+ const struct lttng_payload_view pv =
+ lttng_payload_view_from_payload(
+ &received_payload, 0,
+ -1);
+ const int fd_handle_count =
+ lttng_payload_view_get_fd_handle_count(
+ &pv);
+
+ ok(fd_handle_count == 1,
+ "Payload contains 1 fd for message %u",
+ i);
+ }
+
+ lttng_payload_clear(&received_payload);
+ }
+
+error:
+ for (i = 0; i < 2; i++) {
+ if (sockets[i] < 0) {
+ continue;
+ }
+
+ if (close(sockets[i])) {
+ PERROR("Failed to close unix socket");
+ }
+ }
+
+ lttng_payload_reset(&sent_payload);
+ lttng_payload_reset(&received_payload);
+}
+
+/*
+ * Validate that a large message can be received in multiple chunks.
+ */
+static void test_receive_in_chunks(
+ unsigned int payload_size, unsigned int max_recv_size)
+{
+ int sockets[2] = {-1, -1};
+ int ret;
+ unsigned int i;
+ struct lttng_payload sent_payload;
+ struct lttng_payload received_payload;
+ struct fd_handle *handle;
+ int fd;
+ ssize_t sock_ret, received = 0;
+
+ diag("Receive a message in multiple chunks");
+ lttng_payload_init(&sent_payload);
+ lttng_payload_init(&received_payload);
+
+ ret = lttcomm_create_anon_unix_socketpair(sockets);
+ ok(ret == 0, "Created anonymous unix socket pair");
+ if (ret < 0) {
+ PERROR("Failed to create an anonymous pair of unix sockets");
+ goto error;
+ }
+
+ /* Add dummy content to payload. */
+ ret = lttng_dynamic_buffer_set_size(&sent_payload.buffer, payload_size);
+ if (ret) {
+ PERROR("Failed to initialize test payload");
+ goto error;
+ }
+
+ fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
+ if (fd < 0) {
+ PERROR("Failed to create fd while creating test payload");
+ goto error;
+ }
+
+ handle = fd_handle_create(fd);
+ if (!handle) {
+ if (close(fd)) {
+ PERROR("Failed to close fd while preparing test payload");
+ goto error;
+ }
+ }
+
+ ret = lttng_payload_push_fd_handle(&sent_payload, handle);
+ fd_handle_put(handle);
+ if (ret) {
+ PERROR("Failed to add fd handle to test payload");
+ goto error;
+ }
+
+ /* Send payload. */
+ {
+ struct lttng_payload_view pv = lttng_payload_view_from_payload(
+ &sent_payload, 0, -1);
+
+ /* Not expected to block considering the size of the payload. */
+ sock_ret = lttcomm_send_unix_sock(
+ sockets[0], pv.buffer.data, pv.buffer.size);
+ ok(sock_ret == pv.buffer.size, "Sent complete test payload");
+ if (sock_ret != pv.buffer.size) {
+ ERR("Failed to send test payload bytes: ret = %zd, expected = %zu",
+ sock_ret, pv.buffer.size);
+ goto error;
+ }
+
+ sock_ret = lttcomm_send_payload_view_fds_unix_sock(
+ sockets[0], &pv);
+ ok(sock_ret == 1, "Sent test payload file descriptors");
+ if (sock_ret != 1) {
+ if (sock_ret < 0) {
+ PERROR("Failed to send test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret, 1);
+ } else {
+ diag("Failed to send test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret, 1);
+ }
+
+ goto error;
+ }
+ }
+
+ /* Receive payload */
+ ret = lttng_dynamic_buffer_set_size(
+ &received_payload.buffer, sent_payload.buffer.size);
+ if (ret) {
+ PERROR("Failed to pre-allocate reception buffer");
+ goto error;
+ }
+
+ do {
+ const ssize_t to_receive_this_pass =
+ std::min<ssize_t>(max_recv_size,
+ sent_payload.buffer.size - received);
+
+ sock_ret = lttcomm_recv_unix_sock(sockets[1],
+ received_payload.buffer.data + received,
+ to_receive_this_pass);
+ if (sock_ret != to_receive_this_pass) {
+ ERR("Failed to receive payload bytes: ret = %zd, expected = %zu",
+ sock_ret, to_receive_this_pass);
+ break;
+ }
+
+ received += sock_ret;
+ } while (received < sent_payload.buffer.size);
+
+ ok(received == sent_payload.buffer.size,
+ "Received complete payload in chunks of %u bytes",
+ max_recv_size);
+ if (received != sent_payload.buffer.size) {
+ goto error;
+ }
+
+ sock_ret = lttcomm_recv_payload_fds_unix_sock(
+ sockets[1], 1, &received_payload);
+ ok(sock_ret == (int) sizeof(int),
+ "Received file descriptor after receiving payload in chunks");
+ if (sock_ret != (int) sizeof(int)) {
+ ERR("Failed to receive test payload file descriptors: ret = %zd, expected = %d",
+ sock_ret, (int) sizeof(int));
+ goto error;
+ }
+
+ {
+ const struct lttng_payload_view pv =
+ lttng_payload_view_from_payload(
+ &received_payload, 0, -1);
+ const int fd_handle_count =
+ lttng_payload_view_get_fd_handle_count(&pv);
+
+ ok(fd_handle_count == 1,
+ "Payload contains 1 fd after receiving payload in chunks");
+ }
+
+error:
+ for (i = 0; i < 2; i++) {
+ if (sockets[i] < 0) {
+ continue;
+ }
+
+ if (close(sockets[i])) {
+ PERROR("Failed to close unix socket");
+ }
+ }
+
+ lttng_payload_reset(&sent_payload);
+ lttng_payload_reset(&received_payload);
+}
+
+static
+void test_creds_passing(void)
+{
+ pid_t fork_ret = -1;
+ int ret, parent_socket = -1, child_connection_socket = -1;
+ ssize_t sock_ret;
+ char socket_dir_path[] = "/tmp/test.unix.socket.creds.passing.XXXXXX";
+ char socket_path[PATH_MAX] = {};
+ struct expected_creds {
+ uid_t euid;
+ gid_t egid;
+ pid_t pid;
+ } expected_creds;
+
+ diag("Receive peer's effective uid, effective gid, and pid from a unix socket");
+
+ if (!mkdtemp(socket_dir_path)) {
+ PERROR("Failed to generate temporary socket location");
+ goto error;
+ }
+
+ strncat(socket_path, socket_dir_path,
+ sizeof(socket_path) - strlen(socket_path) - 1);
+ strncat(socket_path, "/test_unix_socket",
+ sizeof(socket_path) - strlen(socket_path) - 1);
+
+ parent_socket = lttcomm_create_unix_sock(socket_path);
+ ok(parent_socket >= 0, "Created unix socket at path `%s`", socket_path);
+ if (parent_socket < 0) {
+ PERROR("Failed to create unix socket at path `%s`", socket_path);
+ goto error;
+ }
+
+ ret = lttcomm_listen_unix_sock(parent_socket);
+ if (ret < 0) {
+ PERROR("Failed to mark parent socket as a passive socket");
+ goto error;
+ }
+
+ ret = lttcomm_setsockopt_creds_unix_sock(parent_socket);
+ if (ret) {
+ PERROR("Failed to set SO_PASSCRED on parent socket");
+ goto error;
+ }
+
+ fork_ret = fork();
+ if (fork_ret < 0) {
+ PERROR("Failed to fork");
+ goto error;
+ }
+
+ if (fork_ret == 0) {
+ /* Child. */
+ int child_socket;
+
+ expected_creds = (struct expected_creds){
+ .euid = geteuid(),
+ .egid = getegid(),
+ .pid = getpid(),
+ };
+
+ child_socket = lttcomm_connect_unix_sock(socket_path);
+ if (child_socket < 0) {
+ PERROR("Failed to connect to parent socket");
+ goto error;
+ }
+
+ ret = lttcomm_setsockopt_creds_unix_sock(child_socket);
+ if (ret) {
+ PERROR("Failed to set SO_PASSCRED on child socket");
+ }
+
+ sock_ret = lttcomm_send_creds_unix_sock(child_socket, &expected_creds,
+ sizeof(expected_creds));
+ if (sock_ret < 0) {
+ PERROR("Failed to send expected credentials");
+ }
+
+ ret = close(child_socket);
+ if (ret) {
+ PERROR("Failed to close child socket");
+ }
+ } else {
+ /* Parent. */
+ int child_status;
+ pid_t wait_pid_ret;
+ lttng_sock_cred received_creds = {};
+
+ child_connection_socket =
+ lttcomm_accept_unix_sock(parent_socket);
+ if (child_connection_socket < 0) {
+ PERROR();
+ goto error;
+ }
+
+ ret = lttcomm_setsockopt_creds_unix_sock(
+ child_connection_socket);
+ if (ret) {
+ PERROR("Failed to set SO_PASSCRED on child connection socket");
+ goto error;
+ }
+
+ sock_ret = lttcomm_recv_creds_unix_sock(child_connection_socket,
+ &expected_creds, sizeof(expected_creds),
+ &received_creds);
+ if (sock_ret < 0) {
+ PERROR("Failed to receive credentials");
+ goto error;
+ }
+
+ wait_pid_ret = waitpid(fork_ret, &child_status, 0);
+ if (wait_pid_ret == -1) {
+ PERROR("Failed to wait for termination of child process");
+ goto error;
+ }
+ if (!WIFEXITED(child_status) || WEXITSTATUS(child_status)) {
+ diag("Child process reported an error, test failed");
+ goto error;
+ }
+
+ ok(expected_creds.euid == received_creds.uid,
+ "Received the expected effective uid (%d == %d)",
+ expected_creds.euid, received_creds.uid);
+ ok(expected_creds.egid == received_creds.gid,
+ "Received the expected effective gid (%d == %d)",
+ expected_creds.egid, received_creds.gid);
+ ok(expected_creds.pid == received_creds.pid,
+ "Received the expected pid (%d == %d)",
+ expected_creds.pid, received_creds.pid);
+ }
+
+error:
+ if (parent_socket >= 0) {
+ ret = close(parent_socket);
+ if (ret) {
+ PERROR("Failed to close parent socket");
+ }
+ }
+
+ if (fork_ret == 0) {
+ /* Prevent libtap from printing a result for the child. */
+ fclose(stdout);
+ fclose(stderr);
+
+ /* Child exits at the end of this test. */
+ exit(0);
+ } else if (parent_socket >= 0) {
+ if (child_connection_socket >= 0) {
+ ret = close(child_connection_socket);
+ if (ret) {
+ PERROR("Failed to close child connection socket");
+ }
+ }
+
+ ret = unlink(socket_path);
+ if (ret) {
+ PERROR("Failed to unlink socket at path `%s`",
+ socket_path);
+ }
+
+ ret = rmdir(socket_dir_path);
+ if (ret) {
+ PERROR("Failed to remove test directory at `%s`",
+ socket_dir_path);
+ }
+ }
+}
+
+int main(void)
+{
+ plan_tests(TEST_COUNT);
+
+ test_high_fd_count(HIGH_FD_COUNT);
+ test_one_fd_per_message(MESSAGE_COUNT);
+ test_receive_in_chunks(LARGE_PAYLOAD_SIZE, LARGE_PAYLOAD_RECV_SIZE);
+ test_creds_passing();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <string.h>
-
-#include <tap/tap.h>
-
-#include <common/uri.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose = 3;
-int lttng_opt_mi;
-
-/* Number of TAP tests in this file */
-#define NUM_TESTS 11
-
-static void test_uri_parsing(void)
-{
- ssize_t size;
- const char *s_uri1;
- struct lttng_uri *uri = NULL;
-
- s_uri1 = "net://localhost";
-
- size = uri_parse(s_uri1, &uri);
-
- ok(size == 2 &&
- uri[0].dtype == LTTNG_DST_IPV4 &&
- uri[0].utype == LTTNG_URI_DST &&
- uri[0].stype == 0 &&
- uri[0].port == 0 &&
- strlen(uri[0].subdir) == 0 &&
- strcmp(uri[0].dst.ipv4, "127.0.0.1") == 0 &&
- uri[1].dtype == LTTNG_DST_IPV4 &&
- uri[1].utype == LTTNG_URI_DST &&
- uri[1].stype == 0 &&
- uri[1].port == 0 &&
- strlen(uri[1].subdir) == 0 &&
- strcmp(uri[1].dst.ipv4, "127.0.0.1") == 0,
- "URI set to net://localhost");
-
- if (uri) {
- uri_free(uri);
- uri = NULL;
- }
-
- s_uri1 = "net://localhost:8989:4242/my/test/path";
-
- size = uri_parse(s_uri1, &uri);
-
- ok(size == 2 &&
- uri[0].dtype == LTTNG_DST_IPV4 &&
- uri[0].utype == LTTNG_URI_DST &&
- uri[0].stype == 0 &&
- uri[0].port == 8989 &&
- strcmp(uri[0].subdir, "my/test/path") == 0 &&
- strcmp(uri[0].dst.ipv4, "127.0.0.1") == 0 &&
- uri[1].dtype == LTTNG_DST_IPV4 &&
- uri[1].utype == LTTNG_URI_DST &&
- uri[1].stype == 0 &&
- uri[1].port == 4242 &&
- strlen(uri[1].subdir) == 0 &&
- strcmp(uri[1].dst.ipv4, "127.0.0.1") == 0,
- "URI set to net://localhost:8989:4242/my/test/path");
-
- if (uri) {
- uri_free(uri);
- uri = NULL;
- }
-
- s_uri1 = "net://localhost:8989:4242";
-
- size = uri_parse(s_uri1, &uri);
-
- ok(size == 2 &&
- uri[0].dtype == LTTNG_DST_IPV4 &&
- uri[0].utype == LTTNG_URI_DST &&
- uri[0].stype == 0 &&
- uri[0].port == 8989 &&
- strlen(uri[0].subdir) == 0 &&
- strcmp(uri[0].dst.ipv4, "127.0.0.1") == 0 &&
- uri[1].dtype == LTTNG_DST_IPV4 &&
- uri[1].utype == LTTNG_URI_DST &&
- uri[1].stype == 0 &&
- uri[1].port == 4242 &&
- strlen(uri[1].subdir) == 0 &&
- strcmp(uri[1].dst.ipv4, "127.0.0.1") == 0,
- "URI set to net://localhost:8989:4242");
-
- if (uri) {
- uri_free(uri);
- uri = NULL;
- }
-
- s_uri1 = "net6://[::1]:8989";
-
- size = uri_parse(s_uri1, &uri);
-
- ok(size == 2 &&
- uri[0].dtype == LTTNG_DST_IPV6 &&
- uri[0].utype == LTTNG_URI_DST &&
- uri[0].stype == 0 &&
- uri[0].port == 8989 &&
- strlen(uri[0].subdir) == 0 &&
- strcmp(uri[0].dst.ipv6, "::1") == 0 &&
- uri[1].dtype == LTTNG_DST_IPV6 &&
- uri[1].utype == LTTNG_URI_DST &&
- uri[1].stype == 0 &&
- uri[1].port == 0 &&
- strlen(uri[1].subdir) == 0 &&
- strcmp(uri[1].dst.ipv6, "::1") == 0,
- "URI set to net6://[::1]:8989");
-
- if (uri) {
- uri_free(uri);
- uri = NULL;
- }
-
- s_uri1 = "tcp://42.42.42.42/my/test/path";
-
- size = uri_parse(s_uri1, &uri);
-
- ok(size == 1 &&
- uri[0].dtype == LTTNG_DST_IPV4 &&
- uri[0].utype == LTTNG_URI_DST &&
- uri[0].stype == 0 &&
- uri[0].port == 0 &&
- strcmp(uri[0].subdir, "my/test/path") == 0 &&
- strcmp(uri[0].dst.ipv4, "42.42.42.42") == 0,
- "URI set to tcp://42.42.42.42/my/test/path");
-
- if (uri) {
- uri_free(uri);
- uri = NULL;
- }
-
- s_uri1 = "tcp6://[fe80::f66d:4ff:fe53:d220]/my/test/path";
-
- size = uri_parse(s_uri1, &uri);
-
- ok(size == 1 &&
- uri[0].dtype == LTTNG_DST_IPV6 &&
- uri[0].utype == LTTNG_URI_DST &&
- uri[0].stype == 0 &&
- uri[0].port == 0 &&
- strcmp(uri[0].subdir, "my/test/path") == 0 &&
- strcmp(uri[0].dst.ipv6, "fe80::f66d:4ff:fe53:d220") == 0,
- "URI set to tcp6://[fe80::f66d:4ff:fe53:d220]/my/test/path");
-
- if (uri) {
- uri_free(uri);
- uri = NULL;
- }
-
- s_uri1 = "file:///my/test/path";
-
- size = uri_parse(s_uri1, &uri);
-
- ok(size == 1 &&
- uri[0].dtype == LTTNG_DST_PATH &&
- uri[0].utype == LTTNG_URI_DST &&
- uri[0].stype == 0 &&
- uri[0].port == 0 &&
- strlen(uri[0].subdir) == 0 &&
- strcmp(uri[0].dst.path, "/my/test/path") == 0,
- "URI set to file:///my/test/path");
-
- if (uri) {
- uri_free(uri);
- uri = NULL;
- }
-
- /* FIXME: Noisy on stdout */
- s_uri1 = "file/my/test/path";
- size = uri_parse(s_uri1, &uri);
- ok(size == -1, "Bad URI set to file/my/test/path");
- LTTNG_ASSERT(!uri);
-
- s_uri1 = "net://:8999";
- size = uri_parse(s_uri1, &uri);
- ok(size == -1, "Bad URI set to net://:8999");
- LTTNG_ASSERT(!uri);
-}
-
-static void test_uri_cmp(void)
-{
- struct lttng_uri *uri1, *uri2;
- const char *s_uri1 = "net://localhost";
- const char *s_uri2 = "net://localhost:8989:4242";
- ssize_t size1, size2;
- int res;
-
- size1 = uri_parse(s_uri1, &uri1);
-
- /* Sanity checks */
- LTTNG_ASSERT(size1 == 2);
- LTTNG_ASSERT(uri1[0].dtype == LTTNG_DST_IPV4);
- LTTNG_ASSERT(uri1[0].utype == LTTNG_URI_DST);
- LTTNG_ASSERT(uri1[0].stype == 0);
- LTTNG_ASSERT(uri1[0].port == 0);
- LTTNG_ASSERT(strlen(uri1[0].subdir) == 0);
- LTTNG_ASSERT(strcmp(uri1[0].dst.ipv4, "127.0.0.1") == 0);
- LTTNG_ASSERT(uri1[1].dtype == LTTNG_DST_IPV4);
- LTTNG_ASSERT(uri1[1].utype == LTTNG_URI_DST);
- LTTNG_ASSERT(uri1[1].stype == 0);
- LTTNG_ASSERT(uri1[1].port == 0);
- LTTNG_ASSERT(strlen(uri1[1].subdir) == 0);
- LTTNG_ASSERT(strcmp(uri1[1].dst.ipv4, "127.0.0.1") == 0);
-
- size2 = uri_parse(s_uri2, &uri2);
-
- LTTNG_ASSERT(size2 == 2);
- LTTNG_ASSERT(uri2[0].dtype == LTTNG_DST_IPV4);
- LTTNG_ASSERT(uri2[0].utype == LTTNG_URI_DST);
- LTTNG_ASSERT(uri2[0].stype == 0);
- LTTNG_ASSERT(uri2[0].port == 8989);
- LTTNG_ASSERT(strlen(uri2[0].subdir) == 0);
- LTTNG_ASSERT(strcmp(uri2[0].dst.ipv4, "127.0.0.1") == 0);
- LTTNG_ASSERT(uri2[1].dtype == LTTNG_DST_IPV4);
- LTTNG_ASSERT(uri2[1].utype == LTTNG_URI_DST);
- LTTNG_ASSERT(uri2[1].stype == 0);
- LTTNG_ASSERT(uri2[1].port == 4242);
- LTTNG_ASSERT(strlen(uri2[1].subdir) == 0);
- LTTNG_ASSERT(strcmp(uri2[1].dst.ipv4, "127.0.0.1") == 0);
-
- res = uri_compare(uri1, uri1);
-
- ok(res == 0,
- "URI compare net://localhost == net://localhost");
-
- res = uri_compare(uri1, uri2);
-
- ok(res != 0,
- "URI compare net://localhost != net://localhost:8989:4242");
-
- uri_free(uri1);
- uri_free(uri2);
-}
-
-int main(int argc, char **argv)
-{
- plan_tests(NUM_TESTS);
-
- diag("URI unit tests");
-
- test_uri_parsing();
-
- test_uri_cmp();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <string.h>
+
+#include <tap/tap.h>
+
+#include <common/uri.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose = 3;
+int lttng_opt_mi;
+
+/* Number of TAP tests in this file */
+#define NUM_TESTS 11
+
+static void test_uri_parsing(void)
+{
+ ssize_t size;
+ const char *s_uri1;
+ struct lttng_uri *uri = NULL;
+
+ s_uri1 = "net://localhost";
+
+ size = uri_parse(s_uri1, &uri);
+
+ ok(size == 2 &&
+ uri[0].dtype == LTTNG_DST_IPV4 &&
+ uri[0].utype == LTTNG_URI_DST &&
+ uri[0].stype == 0 &&
+ uri[0].port == 0 &&
+ strlen(uri[0].subdir) == 0 &&
+ strcmp(uri[0].dst.ipv4, "127.0.0.1") == 0 &&
+ uri[1].dtype == LTTNG_DST_IPV4 &&
+ uri[1].utype == LTTNG_URI_DST &&
+ uri[1].stype == 0 &&
+ uri[1].port == 0 &&
+ strlen(uri[1].subdir) == 0 &&
+ strcmp(uri[1].dst.ipv4, "127.0.0.1") == 0,
+ "URI set to net://localhost");
+
+ if (uri) {
+ uri_free(uri);
+ uri = NULL;
+ }
+
+ s_uri1 = "net://localhost:8989:4242/my/test/path";
+
+ size = uri_parse(s_uri1, &uri);
+
+ ok(size == 2 &&
+ uri[0].dtype == LTTNG_DST_IPV4 &&
+ uri[0].utype == LTTNG_URI_DST &&
+ uri[0].stype == 0 &&
+ uri[0].port == 8989 &&
+ strcmp(uri[0].subdir, "my/test/path") == 0 &&
+ strcmp(uri[0].dst.ipv4, "127.0.0.1") == 0 &&
+ uri[1].dtype == LTTNG_DST_IPV4 &&
+ uri[1].utype == LTTNG_URI_DST &&
+ uri[1].stype == 0 &&
+ uri[1].port == 4242 &&
+ strlen(uri[1].subdir) == 0 &&
+ strcmp(uri[1].dst.ipv4, "127.0.0.1") == 0,
+ "URI set to net://localhost:8989:4242/my/test/path");
+
+ if (uri) {
+ uri_free(uri);
+ uri = NULL;
+ }
+
+ s_uri1 = "net://localhost:8989:4242";
+
+ size = uri_parse(s_uri1, &uri);
+
+ ok(size == 2 &&
+ uri[0].dtype == LTTNG_DST_IPV4 &&
+ uri[0].utype == LTTNG_URI_DST &&
+ uri[0].stype == 0 &&
+ uri[0].port == 8989 &&
+ strlen(uri[0].subdir) == 0 &&
+ strcmp(uri[0].dst.ipv4, "127.0.0.1") == 0 &&
+ uri[1].dtype == LTTNG_DST_IPV4 &&
+ uri[1].utype == LTTNG_URI_DST &&
+ uri[1].stype == 0 &&
+ uri[1].port == 4242 &&
+ strlen(uri[1].subdir) == 0 &&
+ strcmp(uri[1].dst.ipv4, "127.0.0.1") == 0,
+ "URI set to net://localhost:8989:4242");
+
+ if (uri) {
+ uri_free(uri);
+ uri = NULL;
+ }
+
+ s_uri1 = "net6://[::1]:8989";
+
+ size = uri_parse(s_uri1, &uri);
+
+ ok(size == 2 &&
+ uri[0].dtype == LTTNG_DST_IPV6 &&
+ uri[0].utype == LTTNG_URI_DST &&
+ uri[0].stype == 0 &&
+ uri[0].port == 8989 &&
+ strlen(uri[0].subdir) == 0 &&
+ strcmp(uri[0].dst.ipv6, "::1") == 0 &&
+ uri[1].dtype == LTTNG_DST_IPV6 &&
+ uri[1].utype == LTTNG_URI_DST &&
+ uri[1].stype == 0 &&
+ uri[1].port == 0 &&
+ strlen(uri[1].subdir) == 0 &&
+ strcmp(uri[1].dst.ipv6, "::1") == 0,
+ "URI set to net6://[::1]:8989");
+
+ if (uri) {
+ uri_free(uri);
+ uri = NULL;
+ }
+
+ s_uri1 = "tcp://42.42.42.42/my/test/path";
+
+ size = uri_parse(s_uri1, &uri);
+
+ ok(size == 1 &&
+ uri[0].dtype == LTTNG_DST_IPV4 &&
+ uri[0].utype == LTTNG_URI_DST &&
+ uri[0].stype == 0 &&
+ uri[0].port == 0 &&
+ strcmp(uri[0].subdir, "my/test/path") == 0 &&
+ strcmp(uri[0].dst.ipv4, "42.42.42.42") == 0,
+ "URI set to tcp://42.42.42.42/my/test/path");
+
+ if (uri) {
+ uri_free(uri);
+ uri = NULL;
+ }
+
+ s_uri1 = "tcp6://[fe80::f66d:4ff:fe53:d220]/my/test/path";
+
+ size = uri_parse(s_uri1, &uri);
+
+ ok(size == 1 &&
+ uri[0].dtype == LTTNG_DST_IPV6 &&
+ uri[0].utype == LTTNG_URI_DST &&
+ uri[0].stype == 0 &&
+ uri[0].port == 0 &&
+ strcmp(uri[0].subdir, "my/test/path") == 0 &&
+ strcmp(uri[0].dst.ipv6, "fe80::f66d:4ff:fe53:d220") == 0,
+ "URI set to tcp6://[fe80::f66d:4ff:fe53:d220]/my/test/path");
+
+ if (uri) {
+ uri_free(uri);
+ uri = NULL;
+ }
+
+ s_uri1 = "file:///my/test/path";
+
+ size = uri_parse(s_uri1, &uri);
+
+ ok(size == 1 &&
+ uri[0].dtype == LTTNG_DST_PATH &&
+ uri[0].utype == LTTNG_URI_DST &&
+ uri[0].stype == 0 &&
+ uri[0].port == 0 &&
+ strlen(uri[0].subdir) == 0 &&
+ strcmp(uri[0].dst.path, "/my/test/path") == 0,
+ "URI set to file:///my/test/path");
+
+ if (uri) {
+ uri_free(uri);
+ uri = NULL;
+ }
+
+ /* FIXME: Noisy on stdout */
+ s_uri1 = "file/my/test/path";
+ size = uri_parse(s_uri1, &uri);
+ ok(size == -1, "Bad URI set to file/my/test/path");
+ LTTNG_ASSERT(!uri);
+
+ s_uri1 = "net://:8999";
+ size = uri_parse(s_uri1, &uri);
+ ok(size == -1, "Bad URI set to net://:8999");
+ LTTNG_ASSERT(!uri);
+}
+
+static void test_uri_cmp(void)
+{
+ struct lttng_uri *uri1, *uri2;
+ const char *s_uri1 = "net://localhost";
+ const char *s_uri2 = "net://localhost:8989:4242";
+ ssize_t size1, size2;
+ int res;
+
+ size1 = uri_parse(s_uri1, &uri1);
+
+ /* Sanity checks */
+ LTTNG_ASSERT(size1 == 2);
+ LTTNG_ASSERT(uri1[0].dtype == LTTNG_DST_IPV4);
+ LTTNG_ASSERT(uri1[0].utype == LTTNG_URI_DST);
+ LTTNG_ASSERT(uri1[0].stype == 0);
+ LTTNG_ASSERT(uri1[0].port == 0);
+ LTTNG_ASSERT(strlen(uri1[0].subdir) == 0);
+ LTTNG_ASSERT(strcmp(uri1[0].dst.ipv4, "127.0.0.1") == 0);
+ LTTNG_ASSERT(uri1[1].dtype == LTTNG_DST_IPV4);
+ LTTNG_ASSERT(uri1[1].utype == LTTNG_URI_DST);
+ LTTNG_ASSERT(uri1[1].stype == 0);
+ LTTNG_ASSERT(uri1[1].port == 0);
+ LTTNG_ASSERT(strlen(uri1[1].subdir) == 0);
+ LTTNG_ASSERT(strcmp(uri1[1].dst.ipv4, "127.0.0.1") == 0);
+
+ size2 = uri_parse(s_uri2, &uri2);
+
+ LTTNG_ASSERT(size2 == 2);
+ LTTNG_ASSERT(uri2[0].dtype == LTTNG_DST_IPV4);
+ LTTNG_ASSERT(uri2[0].utype == LTTNG_URI_DST);
+ LTTNG_ASSERT(uri2[0].stype == 0);
+ LTTNG_ASSERT(uri2[0].port == 8989);
+ LTTNG_ASSERT(strlen(uri2[0].subdir) == 0);
+ LTTNG_ASSERT(strcmp(uri2[0].dst.ipv4, "127.0.0.1") == 0);
+ LTTNG_ASSERT(uri2[1].dtype == LTTNG_DST_IPV4);
+ LTTNG_ASSERT(uri2[1].utype == LTTNG_URI_DST);
+ LTTNG_ASSERT(uri2[1].stype == 0);
+ LTTNG_ASSERT(uri2[1].port == 4242);
+ LTTNG_ASSERT(strlen(uri2[1].subdir) == 0);
+ LTTNG_ASSERT(strcmp(uri2[1].dst.ipv4, "127.0.0.1") == 0);
+
+ res = uri_compare(uri1, uri1);
+
+ ok(res == 0,
+ "URI compare net://localhost == net://localhost");
+
+ res = uri_compare(uri1, uri2);
+
+ ok(res != 0,
+ "URI compare net://localhost != net://localhost:8989:4242");
+
+ uri_free(uri1);
+ uri_free(uri2);
+}
+
+int main(int argc, char **argv)
+{
+ plan_tests(NUM_TESTS);
+
+ diag("URI unit tests");
+
+ test_uri_parsing();
+
+ test_uri_cmp();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * test_utils_compat_poll.c
- *
- * Unit tests for the compatibility layer of poll/epoll API.
- *
- * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <tap/tap.h>
-
-#include <common/compat/poll.h>
-#include <common/readwrite.h>
-#include <common/pipe.h>
-#include <common/dynamic-array.h>
-
-/* Verification without trashing test order in the child process */
-#define childok(e, test, ...) do { \
- if (!(e)) { \
- diag(test, ## __VA_ARGS__); \
- _exit(EXIT_FAILURE); \
- } \
-} while(0)
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-/*
- * Non-zero 8-bits arbitrary value below 0x7f to ensure no sign extension
- * occurs. Used to verify that the value is properly propagated through the
- * pipe.
- */
-#define MAGIC_VALUE ((char) 0x5A)
-
-#ifdef HAVE_EPOLL
-#define NUM_TESTS 48
-#else
-#define NUM_TESTS 47
-#endif
-
-#ifdef HAVE_EPOLL
-#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
-#define CLOE_VALUE EPOLL_CLOEXEC
-#else
-#define CLOE_VALUE FD_CLOEXEC
-#endif
-
-static
-void test_epoll_compat(void)
-{
- /*
- * Type conversion present to disable warning of anonymous enum from
- * compiler.
- */
- ok((int) LTTNG_CLOEXEC == (int) CLOE_VALUE, "epoll's CLOEXEC value");
-}
-#endif
-
-static void test_alloc(void)
-{
- struct lttng_poll_event poll_events;
-
- lttng_poll_init(&poll_events);
-
- /* Null pointer */
- ok(lttng_poll_create(NULL, 1, 0) != 0, "Create over NULL pointer fails");
- /* Size 0 */
- ok(lttng_poll_create(&poll_events, 0, 0) != 0, "Create with size 0 fails");
- /* without CLOEXEC */
- ok(lttng_poll_create(&poll_events, 1, 0) == 0, "Create valid poll set succeeds");
- /*
- * lttng_poll_event structure untested due to incompatibility across
- * sublayers. lttng_poll_clean cannot be tested. There is no success
- * criteria. Verify set's max size cases.
- */
- lttng_poll_clean(&poll_events);
-}
-
-/* Tests stuff related to what would be handled with epoll_ctl. */
-static void test_add_del(void)
-{
- struct lttng_poll_event poll_events;
-
- lttng_poll_init(&poll_events);
- ok(lttng_poll_add(NULL, 1, LPOLLIN) != 0, "Adding to NULL set fails");
- ok(lttng_poll_add(&poll_events, 1, LPOLLIN) != 0, "Adding to uninitialized structure fails");
- ok(lttng_poll_add(&poll_events, -1, LPOLLIN) != 0, "Adding invalid FD fails");
-
- ok(lttng_poll_create(&poll_events, 1, 0) == 0, "Create a poll set succeeds");
- ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Set created empty");
-
- ok(lttng_poll_add(NULL, 1, LPOLLIN) != 0, "Adding to NULL set fails");
- ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Set still empty");
- ok(lttng_poll_add(&poll_events, -1, LPOLLIN) != 0, "Adding invalid FD fails");
- ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Set still empty");
-
- ok(lttng_poll_add(&poll_events, 1, LPOLLIN) == 0, "Adding valid FD succeeds");
- ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Nb of elements incremented");
-
- ok(lttng_poll_del(NULL, 1) != 0, "Removing from NULL set fails");
- ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Number of FD in set unchanged");
-
- ok(lttng_poll_del(&poll_events, -1) != 0, "Removing from negative FD fails");
- ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Number of FD in set unchanged");
-
- ok(lttng_poll_del(&poll_events, 2) == 0, "Removing invalid FD still succeeds");
- ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Number of elements unchanged");
-
- ok(lttng_poll_del(&poll_events, 1) == 0, "Removing valid FD succeeds");
- ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Nb of elements decremented");
-
- ok(lttng_poll_del(&poll_events, 1) != 0, "Removing from empty set fails");
- ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Nb of elements unchanged");
-
- lttng_poll_clean(&poll_events);
-}
-
-static void test_mod_wait(void)
-{
- struct lttng_poll_event poll_events;
- struct lttng_poll_event cpoll_events;
- int hupfd[2];
- int infd[2];
- pid_t cpid;
- char rbuf = 0, tbuf = MAGIC_VALUE;
- int wstatus;
-
- lttng_poll_init(&poll_events);
- lttng_poll_init(&cpoll_events);
-
- ok(pipe(hupfd) != -1, "pipe function succeeds");
- ok(pipe(infd) != -1, "pipe function succeeds");
-
- cpid = fork();
- if (cpid == 0) {
- childok(lttng_poll_create(&cpoll_events, 1, 0) == 0, "Create valid poll set succeeds");
- childok(lttng_poll_mod(NULL, infd[0], LPOLLIN) == -1, "lttng_poll_mod with invalid input returns an error");
- childok(lttng_poll_mod(&cpoll_events, infd[0], LPOLLIN) == -1, "lttng_poll_mod with invalid input returns an error");
- childok(lttng_poll_add(&cpoll_events, infd[0], LPOLLHUP) == 0, "Add valid FD succeeds");
- childok(lttng_poll_mod(&cpoll_events, -1, LPOLLIN) == -1, "lttng_poll_mod with invalid input returns an error");
- childok(lttng_poll_mod(&cpoll_events, hupfd[0], LPOLLIN) == 0, "lttng_poll_mod on unincluded FD goes on");
- childok(lttng_poll_mod(&cpoll_events, infd[0], LPOLLIN) == 0, "Modify event type succeeds");
- childok(close(infd[1]) == 0, "Close valid FD succeeds");
- childok(lttng_poll_wait(&cpoll_events, -1) == 1, "Wait on close times out");
- childok(lttng_read(infd[0], &rbuf, 1) == 1, "Data is present in the pipe");
- childok(rbuf == MAGIC_VALUE, "Received data is consistent with transmitted data");
- childok(lttng_poll_del(&cpoll_events, infd[0]) == 0, "Removing valid FD succeeds");
- childok(close(infd[0]) == 0, "Close valid FD succeeds");
- childok(close(hupfd[0]) == 0, "Close valid FD succeeds");
- childok(close(hupfd[1]) == 0, "Close valid FD succeeds");
- lttng_poll_clean(&cpoll_events);
- _exit(EXIT_SUCCESS);
- } else {
- ok(close(hupfd[1]) == 0, "Close valid FD succeeds");
- ok(close(infd[0]) == 0, "Close valid FD succeeds");
-
- ok(lttng_poll_wait(NULL, -1) == -1, "lttng_poll_wait call with invalid input returns error");
-
- ok(lttng_poll_create(&poll_events, 1, 0) == 0, "Create valid poll set succeeds");
- ok(lttng_poll_wait(&poll_events, -1) == -1, "lttng_poll_wait call with invalid input returns error");
- ok(lttng_poll_add(&poll_events, hupfd[0], LPOLLHUP) == 0, "Add valid FD succeeds");
- ok(lttng_write(infd[1], &tbuf, 1) == 1, "Write to pipe succeeds");
- ok(lttng_poll_wait(&poll_events, -1) == 1, "Wakes up on one event");
- ok(lttng_poll_del(&poll_events, hupfd[0]) == 0, "Removing valid FD succeeds");
- ok(close(hupfd[0]) == 0, "Close valid FD succeeds");
- ok(close(infd[1]) == 0, "Close valid FD succeeds");
- lttng_poll_clean(&poll_events);
- ok(waitpid(cpid, &wstatus, 0) == cpid, "Wait for child exit");
- ok(WIFEXITED(wstatus) == 1, "Child process exited");
- ok(WEXITSTATUS(wstatus) == EXIT_SUCCESS, "Child process exited with EXIT_SUCCESS");
- }
-}
-
-static void destroy_pipe(void *pipe)
-{
- lttng_pipe_destroy(pipe);
-}
-
-static int run_active_set_combination(unsigned int fd_count,
- unsigned int active_fds_mask)
-{
- int ret = 0;
- unsigned int i;
- const unsigned int active_fds_count = __builtin_popcount(active_fds_mask);
- struct lttng_poll_event poll_events;
- struct lttng_dynamic_pointer_array pipes;
- struct lttng_pipe *pipe = NULL;
-
- lttng_poll_init(&poll_events);
- lttng_dynamic_pointer_array_init(&pipes, destroy_pipe);
-
- ret = lttng_poll_create(&poll_events, fd_count, 0);
- if (ret) {
- diag("Failed to create poll set for %u file descriptors",
- fd_count);
- goto end;
- }
-
- for (i = 0; i < fd_count; i++) {
- pipe = lttng_pipe_open(0);
-
- if (!pipe) {
- diag("Failed to allocate pipe");
- ret = -1;
- goto end;
- }
-
- ret = lttng_poll_add(&poll_events, lttng_pipe_get_readfd(pipe),
- LPOLLIN);
- if (ret) {
- diag("Failed to add file descriptor to poll set");
- ret = -1;
- goto end;
- }
-
- ret = lttng_dynamic_pointer_array_add_pointer(&pipes, pipe);
- if (ret) {
- diag("Failed to add pipe to pipes array");
- ret = -1;
- goto end;
- }
-
- /* Ownership transferred to the pointer array. */
- pipe = NULL;
- }
-
- /* Write one byte for all active fds that should be active. */
- for (i = 0; i < fd_count; i++) {
- struct lttng_pipe *borrowed_pipe;
-
- /* Should this fd be made active? */
- if (!(active_fds_mask & (1 << i))) {
- continue;
- }
-
- borrowed_pipe = lttng_dynamic_pointer_array_get_pointer(
- &pipes, i);
-
- ret = lttng_pipe_write(
- borrowed_pipe, &(char){'a'}, sizeof(char));
- if (ret != sizeof(char)) {
- diag("Failed to write to pipe");
- ret = -1;
- goto end;
- }
- }
-
- ret = lttng_poll_wait(&poll_events, 0);
- if (ret != active_fds_count) {
- diag("lttng_poll_wait returned %d, expected %u active file descriptors",
- ret, active_fds_count);
- ret = -1;
- goto end;
- } else {
- /* Success! */
- ret = 0;
- }
-
-end:
- lttng_dynamic_pointer_array_reset(&pipes);
- lttng_poll_clean(&poll_events);
- lttng_pipe_destroy(pipe);
- return ret;
-}
-
-static void test_active_set_combinations(unsigned int fd_count)
-{
- unsigned int i, all_active_mask = 0;
-
- /* Do you really want to test more than 4,294,967,295 combinations? */
- LTTNG_ASSERT(fd_count <= 32);
-
- for (i = 0; i < fd_count; i++) {
- all_active_mask |= (1 << i);
- }
-
- for (i = 0; i <= all_active_mask; i++) {
- const int ret = run_active_set_combination(fd_count, i);
-
- if (ret) {
- goto fail;
- }
- }
-
- pass("Test all combinations of active file descriptors for %u file descriptors", fd_count);
- return;
-fail:
- fail("Test all combinations of active file descriptors for %u file descriptors", fd_count);
-}
-
-static void test_func_def(void)
-{
-#ifdef LTTNG_POLL_GETFD
-#define PASS_GETFD 1
-#else
-#define PASS_GETFD 0
-#endif
-
-#ifdef LTTNG_POLL_GETEV
-#define PASS_GETEV 1
-#else
-#define PASS_GETEV 0
-#endif
-
-#ifdef LTTNG_POLL_GETSZ
-#define PASS_GETSZ 1
-#else
-#define PASS_GETSZ 0
-#endif
-
-#ifdef LTTNG_POLL_GET_PREV_FD
-#define PASS_GET_PREV_FD 1
-#else
-#define PASS_GET_PREV_FD 0
-#endif
-
- ok(lttng_poll_reset == lttng_poll_reset, "lttng_poll_reset is defined");
- ok(lttng_poll_init == lttng_poll_init , "lttng_poll_init is defined");
- ok(PASS_GETFD, "GETFD is defined");
- ok(PASS_GETEV, "GETEV is defined");
- ok(PASS_GETSZ, "GETSZ is defined");
- ok(PASS_GET_PREV_FD, "GET_PREV_FD is defined");
-}
-
-int main(void)
-{
- plan_tests(NUM_TESTS);
-#ifdef HAVE_EPOLL
- test_epoll_compat();
-#endif
- test_func_def();
- test_alloc();
- test_add_del();
- test_mod_wait();
- test_active_set_combinations(8);
- return exit_status();
-}
--- /dev/null
+/*
+ * test_utils_compat_poll.c
+ *
+ * Unit tests for the compatibility layer of poll/epoll API.
+ *
+ * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <tap/tap.h>
+
+#include <common/compat/poll.h>
+#include <common/readwrite.h>
+#include <common/pipe.h>
+#include <common/dynamic-array.h>
+
+/* Verification without trashing test order in the child process */
+#define childok(e, test, ...) do { \
+ if (!(e)) { \
+ diag(test, ## __VA_ARGS__); \
+ _exit(EXIT_FAILURE); \
+ } \
+} while(0)
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+/*
+ * Non-zero 8-bits arbitrary value below 0x7f to ensure no sign extension
+ * occurs. Used to verify that the value is properly propagated through the
+ * pipe.
+ */
+#define MAGIC_VALUE ((char) 0x5A)
+
+#ifdef HAVE_EPOLL
+#define NUM_TESTS 48
+#else
+#define NUM_TESTS 47
+#endif
+
+#ifdef HAVE_EPOLL
+#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
+#define CLOE_VALUE EPOLL_CLOEXEC
+#else
+#define CLOE_VALUE FD_CLOEXEC
+#endif
+
+static
+void test_epoll_compat(void)
+{
+ /*
+ * Type conversion present to disable warning of anonymous enum from
+ * compiler.
+ */
+ ok((int) LTTNG_CLOEXEC == (int) CLOE_VALUE, "epoll's CLOEXEC value");
+}
+#endif
+
+static void test_alloc(void)
+{
+ struct lttng_poll_event poll_events;
+
+ lttng_poll_init(&poll_events);
+
+ /* Null pointer */
+ ok(lttng_poll_create(NULL, 1, 0) != 0, "Create over NULL pointer fails");
+ /* Size 0 */
+ ok(lttng_poll_create(&poll_events, 0, 0) != 0, "Create with size 0 fails");
+ /* without CLOEXEC */
+ ok(lttng_poll_create(&poll_events, 1, 0) == 0, "Create valid poll set succeeds");
+ /*
+ * lttng_poll_event structure untested due to incompatibility across
+ * sublayers. lttng_poll_clean cannot be tested. There is no success
+ * criteria. Verify set's max size cases.
+ */
+ lttng_poll_clean(&poll_events);
+}
+
+/* Tests stuff related to what would be handled with epoll_ctl. */
+static void test_add_del(void)
+{
+ struct lttng_poll_event poll_events;
+
+ lttng_poll_init(&poll_events);
+ ok(lttng_poll_add(NULL, 1, LPOLLIN) != 0, "Adding to NULL set fails");
+ ok(lttng_poll_add(&poll_events, 1, LPOLLIN) != 0, "Adding to uninitialized structure fails");
+ ok(lttng_poll_add(&poll_events, -1, LPOLLIN) != 0, "Adding invalid FD fails");
+
+ ok(lttng_poll_create(&poll_events, 1, 0) == 0, "Create a poll set succeeds");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Set created empty");
+
+ ok(lttng_poll_add(NULL, 1, LPOLLIN) != 0, "Adding to NULL set fails");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Set still empty");
+ ok(lttng_poll_add(&poll_events, -1, LPOLLIN) != 0, "Adding invalid FD fails");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Set still empty");
+
+ ok(lttng_poll_add(&poll_events, 1, LPOLLIN) == 0, "Adding valid FD succeeds");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Nb of elements incremented");
+
+ ok(lttng_poll_del(NULL, 1) != 0, "Removing from NULL set fails");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Number of FD in set unchanged");
+
+ ok(lttng_poll_del(&poll_events, -1) != 0, "Removing from negative FD fails");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Number of FD in set unchanged");
+
+ ok(lttng_poll_del(&poll_events, 2) == 0, "Removing invalid FD still succeeds");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 1, "Number of elements unchanged");
+
+ ok(lttng_poll_del(&poll_events, 1) == 0, "Removing valid FD succeeds");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Nb of elements decremented");
+
+ ok(lttng_poll_del(&poll_events, 1) != 0, "Removing from empty set fails");
+ ok(LTTNG_POLL_GETNB(&poll_events) == 0, "Nb of elements unchanged");
+
+ lttng_poll_clean(&poll_events);
+}
+
+static void test_mod_wait(void)
+{
+ struct lttng_poll_event poll_events;
+ struct lttng_poll_event cpoll_events;
+ int hupfd[2];
+ int infd[2];
+ pid_t cpid;
+ char rbuf = 0, tbuf = MAGIC_VALUE;
+ int wstatus;
+
+ lttng_poll_init(&poll_events);
+ lttng_poll_init(&cpoll_events);
+
+ ok(pipe(hupfd) != -1, "pipe function succeeds");
+ ok(pipe(infd) != -1, "pipe function succeeds");
+
+ cpid = fork();
+ if (cpid == 0) {
+ childok(lttng_poll_create(&cpoll_events, 1, 0) == 0, "Create valid poll set succeeds");
+ childok(lttng_poll_mod(NULL, infd[0], LPOLLIN) == -1, "lttng_poll_mod with invalid input returns an error");
+ childok(lttng_poll_mod(&cpoll_events, infd[0], LPOLLIN) == -1, "lttng_poll_mod with invalid input returns an error");
+ childok(lttng_poll_add(&cpoll_events, infd[0], LPOLLHUP) == 0, "Add valid FD succeeds");
+ childok(lttng_poll_mod(&cpoll_events, -1, LPOLLIN) == -1, "lttng_poll_mod with invalid input returns an error");
+ childok(lttng_poll_mod(&cpoll_events, hupfd[0], LPOLLIN) == 0, "lttng_poll_mod on unincluded FD goes on");
+ childok(lttng_poll_mod(&cpoll_events, infd[0], LPOLLIN) == 0, "Modify event type succeeds");
+ childok(close(infd[1]) == 0, "Close valid FD succeeds");
+ childok(lttng_poll_wait(&cpoll_events, -1) == 1, "Wait on close times out");
+ childok(lttng_read(infd[0], &rbuf, 1) == 1, "Data is present in the pipe");
+ childok(rbuf == MAGIC_VALUE, "Received data is consistent with transmitted data");
+ childok(lttng_poll_del(&cpoll_events, infd[0]) == 0, "Removing valid FD succeeds");
+ childok(close(infd[0]) == 0, "Close valid FD succeeds");
+ childok(close(hupfd[0]) == 0, "Close valid FD succeeds");
+ childok(close(hupfd[1]) == 0, "Close valid FD succeeds");
+ lttng_poll_clean(&cpoll_events);
+ _exit(EXIT_SUCCESS);
+ } else {
+ ok(close(hupfd[1]) == 0, "Close valid FD succeeds");
+ ok(close(infd[0]) == 0, "Close valid FD succeeds");
+
+ ok(lttng_poll_wait(NULL, -1) == -1, "lttng_poll_wait call with invalid input returns error");
+
+ ok(lttng_poll_create(&poll_events, 1, 0) == 0, "Create valid poll set succeeds");
+ ok(lttng_poll_wait(&poll_events, -1) == -1, "lttng_poll_wait call with invalid input returns error");
+ ok(lttng_poll_add(&poll_events, hupfd[0], LPOLLHUP) == 0, "Add valid FD succeeds");
+ ok(lttng_write(infd[1], &tbuf, 1) == 1, "Write to pipe succeeds");
+ ok(lttng_poll_wait(&poll_events, -1) == 1, "Wakes up on one event");
+ ok(lttng_poll_del(&poll_events, hupfd[0]) == 0, "Removing valid FD succeeds");
+ ok(close(hupfd[0]) == 0, "Close valid FD succeeds");
+ ok(close(infd[1]) == 0, "Close valid FD succeeds");
+ lttng_poll_clean(&poll_events);
+ ok(waitpid(cpid, &wstatus, 0) == cpid, "Wait for child exit");
+ ok(WIFEXITED(wstatus) == 1, "Child process exited");
+ ok(WEXITSTATUS(wstatus) == EXIT_SUCCESS, "Child process exited with EXIT_SUCCESS");
+ }
+}
+
+static void destroy_pipe(void *pipe)
+{
+ lttng_pipe_destroy((lttng_pipe *) pipe);
+}
+
+static int run_active_set_combination(unsigned int fd_count,
+ unsigned int active_fds_mask)
+{
+ int ret = 0;
+ unsigned int i;
+ const unsigned int active_fds_count = __builtin_popcount(active_fds_mask);
+ struct lttng_poll_event poll_events;
+ struct lttng_dynamic_pointer_array pipes;
+ struct lttng_pipe *pipe = NULL;
+
+ lttng_poll_init(&poll_events);
+ lttng_dynamic_pointer_array_init(&pipes, destroy_pipe);
+
+ ret = lttng_poll_create(&poll_events, fd_count, 0);
+ if (ret) {
+ diag("Failed to create poll set for %u file descriptors",
+ fd_count);
+ goto end;
+ }
+
+ for (i = 0; i < fd_count; i++) {
+ pipe = lttng_pipe_open(0);
+
+ if (!pipe) {
+ diag("Failed to allocate pipe");
+ ret = -1;
+ goto end;
+ }
+
+ ret = lttng_poll_add(&poll_events, lttng_pipe_get_readfd(pipe),
+ LPOLLIN);
+ if (ret) {
+ diag("Failed to add file descriptor to poll set");
+ ret = -1;
+ goto end;
+ }
+
+ ret = lttng_dynamic_pointer_array_add_pointer(&pipes, pipe);
+ if (ret) {
+ diag("Failed to add pipe to pipes array");
+ ret = -1;
+ goto end;
+ }
+
+ /* Ownership transferred to the pointer array. */
+ pipe = NULL;
+ }
+
+ /* Write one byte for all active fds that should be active. */
+ for (i = 0; i < fd_count; i++) {
+ struct lttng_pipe *borrowed_pipe;
+
+ /* Should this fd be made active? */
+ if (!(active_fds_mask & (1 << i))) {
+ continue;
+ }
+
+ borrowed_pipe =
+ (lttng_pipe *) lttng_dynamic_pointer_array_get_pointer(
+ &pipes, i);
+
+ char c = 'a';
+ ret = lttng_pipe_write(
+ borrowed_pipe, &c, sizeof(char));
+ if (ret != sizeof(char)) {
+ diag("Failed to write to pipe");
+ ret = -1;
+ goto end;
+ }
+ }
+
+ ret = lttng_poll_wait(&poll_events, 0);
+ if (ret != active_fds_count) {
+ diag("lttng_poll_wait returned %d, expected %u active file descriptors",
+ ret, active_fds_count);
+ ret = -1;
+ goto end;
+ } else {
+ /* Success! */
+ ret = 0;
+ }
+
+end:
+ lttng_dynamic_pointer_array_reset(&pipes);
+ lttng_poll_clean(&poll_events);
+ lttng_pipe_destroy(pipe);
+ return ret;
+}
+
+static void test_active_set_combinations(unsigned int fd_count)
+{
+ unsigned int i, all_active_mask = 0;
+
+ /* Do you really want to test more than 4,294,967,295 combinations? */
+ LTTNG_ASSERT(fd_count <= 32);
+
+ for (i = 0; i < fd_count; i++) {
+ all_active_mask |= (1 << i);
+ }
+
+ for (i = 0; i <= all_active_mask; i++) {
+ const int ret = run_active_set_combination(fd_count, i);
+
+ if (ret) {
+ goto fail;
+ }
+ }
+
+ pass("Test all combinations of active file descriptors for %u file descriptors", fd_count);
+ return;
+fail:
+ fail("Test all combinations of active file descriptors for %u file descriptors", fd_count);
+}
+
+static void test_func_def(void)
+{
+#ifdef LTTNG_POLL_GETFD
+#define PASS_GETFD 1
+#else
+#define PASS_GETFD 0
+#endif
+
+#ifdef LTTNG_POLL_GETEV
+#define PASS_GETEV 1
+#else
+#define PASS_GETEV 0
+#endif
+
+#ifdef LTTNG_POLL_GETSZ
+#define PASS_GETSZ 1
+#else
+#define PASS_GETSZ 0
+#endif
+
+#ifdef LTTNG_POLL_GET_PREV_FD
+#define PASS_GET_PREV_FD 1
+#else
+#define PASS_GET_PREV_FD 0
+#endif
+
+ ok(lttng_poll_reset == lttng_poll_reset, "lttng_poll_reset is defined");
+ ok(lttng_poll_init == lttng_poll_init , "lttng_poll_init is defined");
+ ok(PASS_GETFD, "GETFD is defined");
+ ok(PASS_GETEV, "GETEV is defined");
+ ok(PASS_GETSZ, "GETSZ is defined");
+ ok(PASS_GET_PREV_FD, "GET_PREV_FD is defined");
+}
+
+int main(void)
+{
+ plan_tests(NUM_TESTS);
+#ifdef HAVE_EPOLL
+ test_epoll_compat();
+#endif
+ test_func_def();
+ test_alloc();
+ test_add_del();
+ test_mod_wait();
+ test_active_set_combinations(8);
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "common/compat/pthread.h"
-
-#include <tap/tap.h>
-
-#define TEST_NAME_PROPER_LEN 16
-
-int main(int argc, char **argv)
-{
- int ret;
- char name1[TEST_NAME_PROPER_LEN];
- char name2[TEST_NAME_PROPER_LEN];
- char too_long_name[] = "thisnameistoolong";
- char short_name[] = "labatt50";
- char long_name[] = "procrastinating";
-
- plan_tests(10);
-
- /* Get the initial thread name */
- ret = lttng_pthread_getname_np(name1, TEST_NAME_PROPER_LEN);
- ok(ret == 0, "Get the thread name: '%s'", name1);
-
- /* Set a thread name of more than 16 bytes, should fail */
- ret = lttng_pthread_setname_np(too_long_name);
- ok(ret == ERANGE, "Set a too long thread name: '%s'", too_long_name);
-
- /* Get the thread name again, shouldn't have changed */
- ret = lttng_pthread_getname_np(name2, TEST_NAME_PROPER_LEN);
- ok(ret == 0, "Get the thread name: '%s'", name2);
- ok(strcmp(name1, name2) == 0, "Compare the initial thread name: '%s' == '%s'", name1, name2);
-
- /* Set a thread name of less than 16 bytes */
- ret = lttng_pthread_setname_np(short_name);
- ok(ret == 0, "Set a short thread name: '%s'", short_name);
-
- /* Get the thread name again, should be the one we set */
- ret = lttng_pthread_getname_np(name1, TEST_NAME_PROPER_LEN);
- ok(ret == 0, "Get a short thread name: '%s'", name1);
- ok(strcmp(short_name, name1) == 0, "Compare the short thread name: '%s' == '%s'", short_name, name1);
-
-
- /* Set a thread name of 16 bytes */
- ret = lttng_pthread_setname_np(long_name);
- ok(ret == 0, "Set a long thread name: '%s'", long_name);
-
- /* Get the thread name again, should be the one we set */
- ret = lttng_pthread_getname_np(name1, TEST_NAME_PROPER_LEN);
- ok(ret == 0, "Get a long thread name: '%s'", name1);
- ok(strncmp(long_name, name1, TEST_NAME_PROPER_LEN - 1) == 0, "Compare the long thread name: '%s' == '%s'", long_name, name1);
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "common/compat/pthread.h"
+
+#include <tap/tap.h>
+
+#define TEST_NAME_PROPER_LEN 16
+
+int main(int argc, char **argv)
+{
+ int ret;
+ char name1[TEST_NAME_PROPER_LEN];
+ char name2[TEST_NAME_PROPER_LEN];
+ char too_long_name[] = "thisnameistoolong";
+ char short_name[] = "labatt50";
+ char long_name[] = "procrastinating";
+
+ plan_tests(10);
+
+ /* Get the initial thread name */
+ ret = lttng_pthread_getname_np(name1, TEST_NAME_PROPER_LEN);
+ ok(ret == 0, "Get the thread name: '%s'", name1);
+
+ /* Set a thread name of more than 16 bytes, should fail */
+ ret = lttng_pthread_setname_np(too_long_name);
+ ok(ret == ERANGE, "Set a too long thread name: '%s'", too_long_name);
+
+ /* Get the thread name again, shouldn't have changed */
+ ret = lttng_pthread_getname_np(name2, TEST_NAME_PROPER_LEN);
+ ok(ret == 0, "Get the thread name: '%s'", name2);
+ ok(strcmp(name1, name2) == 0, "Compare the initial thread name: '%s' == '%s'", name1, name2);
+
+ /* Set a thread name of less than 16 bytes */
+ ret = lttng_pthread_setname_np(short_name);
+ ok(ret == 0, "Set a short thread name: '%s'", short_name);
+
+ /* Get the thread name again, should be the one we set */
+ ret = lttng_pthread_getname_np(name1, TEST_NAME_PROPER_LEN);
+ ok(ret == 0, "Get a short thread name: '%s'", name1);
+ ok(strcmp(short_name, name1) == 0, "Compare the short thread name: '%s' == '%s'", short_name, name1);
+
+
+ /* Set a thread name of 16 bytes */
+ ret = lttng_pthread_setname_np(long_name);
+ ok(ret == 0, "Set a long thread name: '%s'", long_name);
+
+ /* Get the thread name again, should be the one we set */
+ ret = lttng_pthread_getname_np(name1, TEST_NAME_PROPER_LEN);
+ ok(ret == 0, "Get a long thread name: '%s'", name1);
+ ok(strncmp(long_name, name1, TEST_NAME_PROPER_LEN - 1) == 0, "Compare the long thread name: '%s' == '%s'", long_name, name1);
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2013 Raphaël Beamonte <raphael.beamonte@gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <tap/tap.h>
-
-#include <common/utils.h>
-#include <common/common.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose = 3;
-int lttng_opt_mi;
-
-struct valid_test_input {
- const char *input;
- const char *relative_part;
- const char *absolute_part;
-};
-
-struct tree_symlink {
- const char *orig;
- const char *dest;
-};
-
-struct symlink_test_input {
- const char *input;
- const char *expected_result;
-};
-
-/* Valid test cases */
-static struct valid_test_input valid_tests_inputs[] = {
- { "/a/b/c/d/e", "", "/a/b/c/d/e" },
- { "/a//b//c/d/e", "", "/a/b/c/d/e" },
- { "./a/b/c/d/e", ".", "/a/b/c/d/e" },
- { "../a/b/c/d/../e", "..", "/a/b/c/e" },
- { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
- { "../../a/b/c/d/e", "../..", "/a/b/c/d/e" },
- { "./a/b/../c/d/../e", ".", "/a/c/e" },
- { "../a/b/../../c/./d/./e", "..", "/c/d/e" },
- { "../../a/b/../c/d/../../e", "../..", "/a/e" },
- { "./a/b/c/d/../../../../e", ".", "/e" },
- { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
- { "a/", ".", "/a/" },
- { "a", ".", "/a" },
- { "../../", "../..", "/" },
- { "../..", "../..", "" },
- { "../", "..", "/" },
- { "..", "..", "" },
- { "./", ".", "/" },
- { ".", ".", "" },
- { "/../a/b/c/d/e", "", "/a/b/c/d/e" },
- { "/a/b/c/d/../../../../../e", "", "/e" },
- { "/..", "", "/" },
- { "/a/..", "", "/" },
-};
-char **valid_tests_expected_results;
-static const int num_valid_tests =
- sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
-
-/* Symlinks test cases */
-char tree_origin[] = "/tmp/test_utils_expand_path.XXXXXX";
-
-static const char * const tree_dirs[] = {
- "a",
- "a/b",
- "a/b/c",
- "a/e",
-};
-static const int num_tree_dirs =
- sizeof(tree_dirs) / sizeof(tree_dirs[0]);
-
-static struct tree_symlink tree_symlinks[] = {
- { "a/d", "b/c/" },
- { "a/g", "d/" },
- { "a/b/f", "../e/" },
- { "a/b/h", "../g/" },
- { "a/b/k", "c/g/" },
- { "a/b/c/g", "../../../" },
-};
-static const int num_tree_symlinks =
- sizeof(tree_symlinks) / sizeof(tree_symlinks[0]);
-
-static struct symlink_test_input symlink_tests_inputs[] = {
- { "a/g/../l/.", "a/b/l" },
- { "a/g/../l/./", "a/b/l/" },
- { "a/g/../l/..", "a/b" },
- { "a/g/../l/../", "a/b/" },
- { "a/b/h/g/", "" },
-};
-static const int num_symlink_tests =
- sizeof(symlink_tests_inputs) / sizeof(symlink_tests_inputs[0]);
-
-/* Invalid test cases */
-static char *invalid_tests_inputs[] = {
- NULL,
-};
-static const int num_invalid_tests =
- sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
-
-#define PRINT_ERR(fmt, args...) \
- fprintf(stderr, "test_utils_expand_path: error: " fmt "\n", ## args)
-
-static int prepare_valid_results(void)
-{
- int i;
- char *relative, *cur_path = NULL, *prev_path = NULL,
- *pprev_path = NULL, *empty = NULL;
- int ret = 0;
-
- /* Prepare the relative paths */
- cur_path = realpath(".", NULL);
- prev_path = realpath("..", NULL);
- pprev_path = realpath("../..", NULL);
- empty = strdup("");
- if (!cur_path || !prev_path || !pprev_path || !empty) {
- PRINT_ERR("strdup out of memory");
- ret = -1;
- goto end;
- }
-
- /* allocate memory for the expected results */
- valid_tests_expected_results = zmalloc(sizeof(char *) * num_valid_tests);
- if (!valid_tests_expected_results) {
- PRINT_ERR("out of memory");
- ret = -1;
- goto end;
- }
- for (i = 0; i < num_valid_tests; i++) {
- valid_tests_expected_results[i] = malloc(PATH_MAX);
- if (valid_tests_expected_results[i] == NULL) {
- PRINT_ERR("malloc expected results");
- ret = -1;
- goto end;
- }
-
- if (strcmp(valid_tests_inputs[i].relative_part, ".") == 0) {
- relative = cur_path;
- } else if (strcmp(valid_tests_inputs[i].relative_part, "..") == 0) {
- relative = prev_path;
- } else if (strcmp(valid_tests_inputs[i].relative_part, "../..") == 0) {
- relative = pprev_path;
- } else {
- relative = empty;
- }
-
- snprintf(valid_tests_expected_results[i], PATH_MAX,
- "%s%s", relative, valid_tests_inputs[i].absolute_part);
- }
-
-end:
- free(cur_path);
- free(prev_path);
- free(pprev_path);
- free(empty);
-
- return ret;
-}
-
-static int free_valid_results(void)
-{
- int i;
-
- for (i = 0; i < num_valid_tests; i++) {
- free(valid_tests_expected_results[i]);
- }
-
- free(valid_tests_expected_results);
-
- return 0;
-}
-
-static int prepare_symlink_tree(void)
-{
- int i;
- char tmppath[PATH_MAX] = {};
-
- /* Create the temporary directory */
- if (mkdtemp(tree_origin) == NULL) {
- PRINT_ERR("failed to mkdtemp");
- goto error;
- }
-
- /* Create the directories of the test tree */
- for (i = 0; i < num_tree_dirs; i++) {
- snprintf(tmppath, sizeof(tmppath), "%s/%s", tree_origin,
- tree_dirs[i]);
-
- if (mkdir(tmppath, 0755) != 0) {
- PRINT_ERR("mkdir failed with path \"%s\"", tmppath);
- goto error;
- }
- }
-
- /* Create the symlinks of the test tree */
- for (i = 0; i < num_tree_symlinks; i++) {
- snprintf(tmppath, sizeof(tmppath), "%s/%s",
- tree_origin, tree_symlinks[i].orig);
-
- if (symlink(tree_symlinks[i].dest, tmppath) != 0) {
- PRINT_ERR("failed to symlink \"%s\" to \"%s\"", tmppath,
- tree_symlinks[i].dest);
- goto error;
- }
- }
-
- return 0;
-
-error:
- return 1;
-}
-
-static int free_symlink_tree(void)
-{
- int i;
- char tmppath[PATH_MAX];
-
- /* Remove the symlinks from the test tree */
- for (i = num_tree_symlinks - 1; i > -1; i--) {
- snprintf(tmppath, PATH_MAX, "%s/%s",
- tree_origin, tree_symlinks[i].orig);
-
- if (unlink(tmppath) != 0) {
- PRINT_ERR("failed to unlink \"%s\"", tmppath);
- goto error;
- }
- }
-
- /* Remove the directories from the test tree */
- for (i = num_tree_dirs - 1; i > -1; i--) {
- snprintf(tmppath, PATH_MAX, "%s/%s", tree_origin, tree_dirs[i]);
-
- if (rmdir(tmppath) != 0) {
- PRINT_ERR("failed to rmdir \"%s\"", tmppath);
- goto error;
- }
- }
-
- /* Remove the temporary directory */
- if (rmdir(tree_origin) != 0) {
- PRINT_ERR("failed to rmdir \"%s\"", tree_origin);
- goto error;
- }
-
- return 0;
-
-error:
- return 1;
-}
-
-static void test_utils_expand_path(void)
-{
- char *result;
- char name[100], tmppath[PATH_MAX], real_tree_origin[PATH_MAX];
- int i, treelen;
-
- /* Test valid cases */
- for (i = 0; i < num_valid_tests; i++) {
- sprintf(name, "valid test case: %s", valid_tests_inputs[i].input);
-
- result = utils_expand_path(valid_tests_inputs[i].input);
- ok(result != NULL &&
- strcmp(result, valid_tests_expected_results[i]) == 0, name);
-
- free(result);
- }
-
- /*
- * Get the realpath for the tree_origin since it can itself be a
- * symlink.
- */
- result = realpath(tree_origin, real_tree_origin);
- if (!result) {
- fail("realpath failed.");
- return;
- }
-
- /* Test symlink tree cases */
- treelen = strlen(real_tree_origin) + 1;
- for (i = 0; i < num_symlink_tests; i++) {
- int ret;
-
- sprintf(name, "symlink tree test case: [tmppath/]%s",
- symlink_tests_inputs[i].input);
-
- ret = snprintf(tmppath, PATH_MAX, "%s/%s",
- real_tree_origin,
- symlink_tests_inputs[i].input);
- if (ret == -1 || ret >= PATH_MAX) {
- PRINT_ERR("truncation occurred while concatenating paths \"%s\" and \"%s\"",
- real_tree_origin,
- symlink_tests_inputs[i].input);
- fail(name);
- continue;
- }
- result = utils_expand_path(tmppath);
- ok(result != NULL && strcmp(result + treelen,
- symlink_tests_inputs[i].expected_result) == 0, name);
-
- free(result);
- }
-
- /* Test invalid cases */
- for (i = 0; i < num_invalid_tests; i++) {
- const char *test_input = invalid_tests_inputs[i];
-
- sprintf(name, "invalid test case: %s", test_input ?
- test_input : "NULL");
-
- result = utils_expand_path(test_input);
- if (result != NULL) {
- free(result);
- }
- ok(result == NULL, name);
- }
-}
-
-int main(int argc, char **argv)
-{
- if (prepare_symlink_tree() != 0) {
- goto error_mkdir;
- }
-
- if (prepare_valid_results() != 0) {
- goto error_malloc;
- }
-
- plan_tests(num_valid_tests + num_invalid_tests + num_symlink_tests);
-
- diag("utils_expand_path tests");
-
- test_utils_expand_path();
-
- free_valid_results();
- free_symlink_tree();
-
- return exit_status();
-
-error_malloc:
- free_valid_results();
-
-error_mkdir:
- free_symlink_tree();
-
- return 1;
-}
--- /dev/null
+/*
+ * Copyright (C) 2013 Raphaël Beamonte <raphael.beamonte@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <tap/tap.h>
+
+#include <common/utils.h>
+#include <common/common.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose = 3;
+int lttng_opt_mi;
+
+struct valid_test_input {
+ const char *input;
+ const char *relative_part;
+ const char *absolute_part;
+};
+
+struct tree_symlink {
+ const char *orig;
+ const char *dest;
+};
+
+struct symlink_test_input {
+ const char *input;
+ const char *expected_result;
+};
+
+/* Valid test cases */
+static struct valid_test_input valid_tests_inputs[] = {
+ { "/a/b/c/d/e", "", "/a/b/c/d/e" },
+ { "/a//b//c/d/e", "", "/a/b/c/d/e" },
+ { "./a/b/c/d/e", ".", "/a/b/c/d/e" },
+ { "../a/b/c/d/../e", "..", "/a/b/c/e" },
+ { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
+ { "../../a/b/c/d/e", "../..", "/a/b/c/d/e" },
+ { "./a/b/../c/d/../e", ".", "/a/c/e" },
+ { "../a/b/../../c/./d/./e", "..", "/c/d/e" },
+ { "../../a/b/../c/d/../../e", "../..", "/a/e" },
+ { "./a/b/c/d/../../../../e", ".", "/e" },
+ { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
+ { "a/", ".", "/a/" },
+ { "a", ".", "/a" },
+ { "../../", "../..", "/" },
+ { "../..", "../..", "" },
+ { "../", "..", "/" },
+ { "..", "..", "" },
+ { "./", ".", "/" },
+ { ".", ".", "" },
+ { "/../a/b/c/d/e", "", "/a/b/c/d/e" },
+ { "/a/b/c/d/../../../../../e", "", "/e" },
+ { "/..", "", "/" },
+ { "/a/..", "", "/" },
+};
+char **valid_tests_expected_results;
+static const int num_valid_tests =
+ sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
+
+/* Symlinks test cases */
+char tree_origin[] = "/tmp/test_utils_expand_path.XXXXXX";
+
+static const char * const tree_dirs[] = {
+ "a",
+ "a/b",
+ "a/b/c",
+ "a/e",
+};
+static const int num_tree_dirs =
+ sizeof(tree_dirs) / sizeof(tree_dirs[0]);
+
+static struct tree_symlink tree_symlinks[] = {
+ { "a/d", "b/c/" },
+ { "a/g", "d/" },
+ { "a/b/f", "../e/" },
+ { "a/b/h", "../g/" },
+ { "a/b/k", "c/g/" },
+ { "a/b/c/g", "../../../" },
+};
+static const int num_tree_symlinks =
+ sizeof(tree_symlinks) / sizeof(tree_symlinks[0]);
+
+static struct symlink_test_input symlink_tests_inputs[] = {
+ { "a/g/../l/.", "a/b/l" },
+ { "a/g/../l/./", "a/b/l/" },
+ { "a/g/../l/..", "a/b" },
+ { "a/g/../l/../", "a/b/" },
+ { "a/b/h/g/", "" },
+};
+static const int num_symlink_tests =
+ sizeof(symlink_tests_inputs) / sizeof(symlink_tests_inputs[0]);
+
+/* Invalid test cases */
+static char *invalid_tests_inputs[] = {
+ NULL,
+};
+static const int num_invalid_tests =
+ sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
+
+#define PRINT_ERR(fmt, args...) \
+ fprintf(stderr, "test_utils_expand_path: error: " fmt "\n", ## args)
+
+static int prepare_valid_results(void)
+{
+ int i;
+ char *relative, *cur_path = NULL, *prev_path = NULL,
+ *pprev_path = NULL, *empty = NULL;
+ int ret = 0;
+
+ /* Prepare the relative paths */
+ cur_path = realpath(".", NULL);
+ prev_path = realpath("..", NULL);
+ pprev_path = realpath("../..", NULL);
+ empty = strdup("");
+ if (!cur_path || !prev_path || !pprev_path || !empty) {
+ PRINT_ERR("strdup out of memory");
+ ret = -1;
+ goto end;
+ }
+
+ /* allocate memory for the expected results */
+ valid_tests_expected_results = (char **) zmalloc(sizeof(char *) * num_valid_tests);
+ if (!valid_tests_expected_results) {
+ PRINT_ERR("out of memory");
+ ret = -1;
+ goto end;
+ }
+ for (i = 0; i < num_valid_tests; i++) {
+ valid_tests_expected_results[i] = (char *) malloc(PATH_MAX);
+ if (valid_tests_expected_results[i] == NULL) {
+ PRINT_ERR("malloc expected results");
+ ret = -1;
+ goto end;
+ }
+
+ if (strcmp(valid_tests_inputs[i].relative_part, ".") == 0) {
+ relative = cur_path;
+ } else if (strcmp(valid_tests_inputs[i].relative_part, "..") == 0) {
+ relative = prev_path;
+ } else if (strcmp(valid_tests_inputs[i].relative_part, "../..") == 0) {
+ relative = pprev_path;
+ } else {
+ relative = empty;
+ }
+
+ snprintf(valid_tests_expected_results[i], PATH_MAX,
+ "%s%s", relative, valid_tests_inputs[i].absolute_part);
+ }
+
+end:
+ free(cur_path);
+ free(prev_path);
+ free(pprev_path);
+ free(empty);
+
+ return ret;
+}
+
+static int free_valid_results(void)
+{
+ int i;
+
+ for (i = 0; i < num_valid_tests; i++) {
+ free(valid_tests_expected_results[i]);
+ }
+
+ free(valid_tests_expected_results);
+
+ return 0;
+}
+
+static int prepare_symlink_tree(void)
+{
+ int i;
+ char tmppath[PATH_MAX] = {};
+
+ /* Create the temporary directory */
+ if (mkdtemp(tree_origin) == NULL) {
+ PRINT_ERR("failed to mkdtemp");
+ goto error;
+ }
+
+ /* Create the directories of the test tree */
+ for (i = 0; i < num_tree_dirs; i++) {
+ snprintf(tmppath, sizeof(tmppath), "%s/%s", tree_origin,
+ tree_dirs[i]);
+
+ if (mkdir(tmppath, 0755) != 0) {
+ PRINT_ERR("mkdir failed with path \"%s\"", tmppath);
+ goto error;
+ }
+ }
+
+ /* Create the symlinks of the test tree */
+ for (i = 0; i < num_tree_symlinks; i++) {
+ snprintf(tmppath, sizeof(tmppath), "%s/%s",
+ tree_origin, tree_symlinks[i].orig);
+
+ if (symlink(tree_symlinks[i].dest, tmppath) != 0) {
+ PRINT_ERR("failed to symlink \"%s\" to \"%s\"", tmppath,
+ tree_symlinks[i].dest);
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ return 1;
+}
+
+static int free_symlink_tree(void)
+{
+ int i;
+ char tmppath[PATH_MAX];
+
+ /* Remove the symlinks from the test tree */
+ for (i = num_tree_symlinks - 1; i > -1; i--) {
+ snprintf(tmppath, PATH_MAX, "%s/%s",
+ tree_origin, tree_symlinks[i].orig);
+
+ if (unlink(tmppath) != 0) {
+ PRINT_ERR("failed to unlink \"%s\"", tmppath);
+ goto error;
+ }
+ }
+
+ /* Remove the directories from the test tree */
+ for (i = num_tree_dirs - 1; i > -1; i--) {
+ snprintf(tmppath, PATH_MAX, "%s/%s", tree_origin, tree_dirs[i]);
+
+ if (rmdir(tmppath) != 0) {
+ PRINT_ERR("failed to rmdir \"%s\"", tmppath);
+ goto error;
+ }
+ }
+
+ /* Remove the temporary directory */
+ if (rmdir(tree_origin) != 0) {
+ PRINT_ERR("failed to rmdir \"%s\"", tree_origin);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ return 1;
+}
+
+static void test_utils_expand_path(void)
+{
+ char *result;
+ char name[100], tmppath[PATH_MAX], real_tree_origin[PATH_MAX];
+ int i, treelen;
+
+ /* Test valid cases */
+ for (i = 0; i < num_valid_tests; i++) {
+ sprintf(name, "valid test case: %s", valid_tests_inputs[i].input);
+
+ result = utils_expand_path(valid_tests_inputs[i].input);
+ ok(result != NULL &&
+ strcmp(result, valid_tests_expected_results[i]) == 0, name);
+
+ free(result);
+ }
+
+ /*
+ * Get the realpath for the tree_origin since it can itself be a
+ * symlink.
+ */
+ result = realpath(tree_origin, real_tree_origin);
+ if (!result) {
+ fail("realpath failed.");
+ return;
+ }
+
+ /* Test symlink tree cases */
+ treelen = strlen(real_tree_origin) + 1;
+ for (i = 0; i < num_symlink_tests; i++) {
+ int ret;
+
+ sprintf(name, "symlink tree test case: [tmppath/]%s",
+ symlink_tests_inputs[i].input);
+
+ ret = snprintf(tmppath, PATH_MAX, "%s/%s",
+ real_tree_origin,
+ symlink_tests_inputs[i].input);
+ if (ret == -1 || ret >= PATH_MAX) {
+ PRINT_ERR("truncation occurred while concatenating paths \"%s\" and \"%s\"",
+ real_tree_origin,
+ symlink_tests_inputs[i].input);
+ fail(name);
+ continue;
+ }
+ result = utils_expand_path(tmppath);
+ ok(result != NULL && strcmp(result + treelen,
+ symlink_tests_inputs[i].expected_result) == 0, name);
+
+ free(result);
+ }
+
+ /* Test invalid cases */
+ for (i = 0; i < num_invalid_tests; i++) {
+ const char *test_input = invalid_tests_inputs[i];
+
+ sprintf(name, "invalid test case: %s", test_input ?
+ test_input : "NULL");
+
+ result = utils_expand_path(test_input);
+ if (result != NULL) {
+ free(result);
+ }
+ ok(result == NULL, name);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (prepare_symlink_tree() != 0) {
+ goto error_mkdir;
+ }
+
+ if (prepare_valid_results() != 0) {
+ goto error_malloc;
+ }
+
+ plan_tests(num_valid_tests + num_invalid_tests + num_symlink_tests);
+
+ diag("utils_expand_path tests");
+
+ test_utils_expand_path();
+
+ free_valid_results();
+ free_symlink_tree();
+
+ return exit_status();
+
+error_malloc:
+ free_valid_results();
+
+error_mkdir:
+ free_symlink_tree();
+
+ return 1;
+}
+++ /dev/null
-/*
- * Copyright (C) 2013 Simon Marchi <simon.marchi@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <string.h>
-#include <stdio.h>
-
-#include <tap/tap.h>
-
-#include <common/utils.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose = 3;
-int lttng_opt_mi;
-
-struct valid_test_input {
- const char *input;
- uint64_t expected_result;
-};
-
-/* Valid test cases */
-static struct valid_test_input valid_tests_inputs[] = {
- { "0", 0 },
- { "1234", 1234 },
- { "0x400", 1024 },
- { "0300", 192 },
- { "16k", 16384 },
- { "128K", 131072 },
- { "0x1234k", 4771840 },
- { "32M", 33554432 },
- { "1024G", 1099511627776ULL },
- { "0X400", 1024 },
- { "0x40a", 1034 },
- { "0X40b", 1035 },
- { "0x40C", 1036 },
- { "0X40D", 1037 },
- { "0x40e", 1038 },
- { "0X40f", 1039 },
- { "00", 0 },
- { "0k", 0 },
- { "0K", 0 },
- { "0M", 0 },
- { "0G", 0 },
- { "00k", 0 },
- { "00K", 0 },
- { "00M", 0 },
- { "00G", 0 },
- { "0x0", 0 },
- { "0X0", 0 },
- { "0x0k", 0 },
- { "0X0K", 0 },
- { "0x0M", 0 },
- { "0X0G", 0 },
- { "0X40G", 68719476736ULL },
- { "0300k", 196608 },
- { "0300K", 196608 },
- { "030M", 25165824 },
- { "020G", 17179869184ULL },
- { "0xa0k", 163840 },
- { "0xa0K", 163840 },
- { "0XA0M", 167772160 },
- { "0xA0G", 171798691840ULL },
-};
-static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
-
-/* Invalid test cases */
-static const char *invalid_tests_inputs[] = {
- "",
- " ",
- "-1",
- "k",
- "4611686018427387904G",
- "0x40g",
- "08",
- "09",
- "0x",
- "x0",
- "0xx0",
- "07kK",
- "0xk",
- "0XM",
- "0xG",
- "0x0MM",
- "0X0GG",
- "0a",
- "0B",
-};
-
-static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
-
-static void test_utils_parse_size_suffix(void)
-{
- uint64_t result;
- int ret;
- int i;
-
- /* Test valid cases */
- for (i = 0; i < num_valid_tests; i++) {
- char name[100];
- sprintf(name, "valid test case: %s", valid_tests_inputs[i].input);
-
- ret = utils_parse_size_suffix(valid_tests_inputs[i].input, &result);
- ok(ret == 0 && result == valid_tests_inputs[i].expected_result, name);
- }
-
- /* Test invalid cases */
- for (i = 0; i < num_invalid_tests; i++) {
- char name[100];
- sprintf(name, "invalid test case: %s", invalid_tests_inputs[i]);
-
- ret = utils_parse_size_suffix(invalid_tests_inputs[i], &result);
- ok(ret != 0, name);
- }
-}
-
-int main(int argc, char **argv)
-{
- plan_tests(num_valid_tests + num_invalid_tests);
-
- diag("utils_parse_size_suffix tests");
-
- test_utils_parse_size_suffix();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2013 Simon Marchi <simon.marchi@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <tap/tap.h>
+
+#include <common/utils.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose = 3;
+int lttng_opt_mi;
+
+struct valid_test_input {
+ const char *input;
+ uint64_t expected_result;
+};
+
+/* Valid test cases */
+static struct valid_test_input valid_tests_inputs[] = {
+ { "0", 0 },
+ { "1234", 1234 },
+ { "0x400", 1024 },
+ { "0300", 192 },
+ { "16k", 16384 },
+ { "128K", 131072 },
+ { "0x1234k", 4771840 },
+ { "32M", 33554432 },
+ { "1024G", 1099511627776ULL },
+ { "0X400", 1024 },
+ { "0x40a", 1034 },
+ { "0X40b", 1035 },
+ { "0x40C", 1036 },
+ { "0X40D", 1037 },
+ { "0x40e", 1038 },
+ { "0X40f", 1039 },
+ { "00", 0 },
+ { "0k", 0 },
+ { "0K", 0 },
+ { "0M", 0 },
+ { "0G", 0 },
+ { "00k", 0 },
+ { "00K", 0 },
+ { "00M", 0 },
+ { "00G", 0 },
+ { "0x0", 0 },
+ { "0X0", 0 },
+ { "0x0k", 0 },
+ { "0X0K", 0 },
+ { "0x0M", 0 },
+ { "0X0G", 0 },
+ { "0X40G", 68719476736ULL },
+ { "0300k", 196608 },
+ { "0300K", 196608 },
+ { "030M", 25165824 },
+ { "020G", 17179869184ULL },
+ { "0xa0k", 163840 },
+ { "0xa0K", 163840 },
+ { "0XA0M", 167772160 },
+ { "0xA0G", 171798691840ULL },
+};
+static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
+
+/* Invalid test cases */
+static const char *invalid_tests_inputs[] = {
+ "",
+ " ",
+ "-1",
+ "k",
+ "4611686018427387904G",
+ "0x40g",
+ "08",
+ "09",
+ "0x",
+ "x0",
+ "0xx0",
+ "07kK",
+ "0xk",
+ "0XM",
+ "0xG",
+ "0x0MM",
+ "0X0GG",
+ "0a",
+ "0B",
+};
+
+static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
+
+static void test_utils_parse_size_suffix(void)
+{
+ uint64_t result;
+ int ret;
+ int i;
+
+ /* Test valid cases */
+ for (i = 0; i < num_valid_tests; i++) {
+ char name[100];
+ sprintf(name, "valid test case: %s", valid_tests_inputs[i].input);
+
+ ret = utils_parse_size_suffix(valid_tests_inputs[i].input, &result);
+ ok(ret == 0 && result == valid_tests_inputs[i].expected_result, name);
+ }
+
+ /* Test invalid cases */
+ for (i = 0; i < num_invalid_tests; i++) {
+ char name[100];
+ sprintf(name, "invalid test case: %s", invalid_tests_inputs[i]);
+
+ ret = utils_parse_size_suffix(invalid_tests_inputs[i], &result);
+ ok(ret != 0, name);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ plan_tests(num_valid_tests + num_invalid_tests);
+
+ diag("utils_parse_size_suffix tests");
+
+ test_utils_parse_size_suffix();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright (C) 2015 Simon Marchi <simon.marchi@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <inttypes.h>
-
-#include <tap/tap.h>
-
-#include <common/utils.h>
-
-/* For error.h */
-int lttng_opt_quiet = 1;
-int lttng_opt_verbose = 3;
-int lttng_opt_mi;
-
-struct valid_test_input {
- const char *input;
- uint64_t expected_result;
-};
-
-/* Valid test cases */
-static struct valid_test_input valid_tests_inputs[] = {
- { "0", 0 },
- { "1234", 1234 },
- { "1234us", 1234 },
- { "16ms", 16000 },
- { "128ms", 128000 },
- { "32s", 32000000 },
- { "1m", 60000000 },
- { "20m", 1200000000 },
- { "1h", 3600000000 },
- { "5h", 18000000000 },
- { "00", 0 },
- { "0us", 0 },
- { "0ms", 0 },
- { "0s", 0 },
- { "0m", 0 },
- { "0h", 0 },
- { "00us", 0 },
- { "00ms", 0 },
- { "00s", 0 },
- { "00m", 0 },
- { "00h", 0 },
- { "12ms", 12000 },
- { "3597us", 3597 },
- { "+5", 5 },
- { "08", 8 },
- { "0145us", 145 },
-};
-static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
-
-/* Invalid test cases */
-static const char *invalid_tests_inputs[] = {
- "",
- " ",
- "-1",
- "m",
- "4611686018427387904s",
- "0x40M",
- "0x",
- "x0",
- "0xx0",
- "07mm",
- "0xm",
- "0Xs",
- "0x0ss",
- "0a",
- "0B",
- "0x3 s",
- "0xbs ",
- "14ns",
- "0xbs",
- "14ns",
- "14ms garbage after value",
- "0x14s",
- "0u",
- "5mS",
- "5Ms",
- "12ussr",
- "67msrp",
- "14si",
- "12mo",
- "53hi",
-};
-static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
-
-static void test_utils_parse_time_suffix(void)
-{
- uint64_t result;
- int ret;
- int i;
-
- /* Test valid cases */
- for (i = 0; i < num_valid_tests; i++) {
- char name[256];
-
- ret = utils_parse_time_suffix(valid_tests_inputs[i].input, &result);
- sprintf(name, "valid test case: %s expected %" PRIu64, valid_tests_inputs[i].input, result);
- ok(ret == 0 && result == valid_tests_inputs[i].expected_result, name);
- }
-
- /* Test invalid cases */
- for (i = 0; i < num_invalid_tests; i++) {
- char name[100];
-
- sprintf(name, "invalid test case: %s", invalid_tests_inputs[i]);
-
- ret = utils_parse_time_suffix(invalid_tests_inputs[i], &result);
- ok(ret != 0, name);
- }
-}
-
-int main(int argc, char **argv)
-{
- plan_tests(num_valid_tests + num_invalid_tests);
-
- diag("utils_parse_time_suffix tests");
-
- test_utils_parse_time_suffix();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright (C) 2015 Simon Marchi <simon.marchi@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <tap/tap.h>
+
+#include <common/utils.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose = 3;
+int lttng_opt_mi;
+
+struct valid_test_input {
+ const char *input;
+ uint64_t expected_result;
+};
+
+/* Valid test cases */
+static struct valid_test_input valid_tests_inputs[] = {
+ { "0", 0 },
+ { "1234", 1234 },
+ { "1234us", 1234 },
+ { "16ms", 16000 },
+ { "128ms", 128000 },
+ { "32s", 32000000 },
+ { "1m", 60000000 },
+ { "20m", 1200000000 },
+ { "1h", 3600000000 },
+ { "5h", 18000000000 },
+ { "00", 0 },
+ { "0us", 0 },
+ { "0ms", 0 },
+ { "0s", 0 },
+ { "0m", 0 },
+ { "0h", 0 },
+ { "00us", 0 },
+ { "00ms", 0 },
+ { "00s", 0 },
+ { "00m", 0 },
+ { "00h", 0 },
+ { "12ms", 12000 },
+ { "3597us", 3597 },
+ { "+5", 5 },
+ { "08", 8 },
+ { "0145us", 145 },
+};
+static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
+
+/* Invalid test cases */
+static const char *invalid_tests_inputs[] = {
+ "",
+ " ",
+ "-1",
+ "m",
+ "4611686018427387904s",
+ "0x40M",
+ "0x",
+ "x0",
+ "0xx0",
+ "07mm",
+ "0xm",
+ "0Xs",
+ "0x0ss",
+ "0a",
+ "0B",
+ "0x3 s",
+ "0xbs ",
+ "14ns",
+ "0xbs",
+ "14ns",
+ "14ms garbage after value",
+ "0x14s",
+ "0u",
+ "5mS",
+ "5Ms",
+ "12ussr",
+ "67msrp",
+ "14si",
+ "12mo",
+ "53hi",
+};
+static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
+
+static void test_utils_parse_time_suffix(void)
+{
+ uint64_t result;
+ int ret;
+ int i;
+
+ /* Test valid cases */
+ for (i = 0; i < num_valid_tests; i++) {
+ char name[256];
+
+ ret = utils_parse_time_suffix(valid_tests_inputs[i].input, &result);
+ sprintf(name, "valid test case: %s expected %" PRIu64, valid_tests_inputs[i].input, result);
+ ok(ret == 0 && result == valid_tests_inputs[i].expected_result, name);
+ }
+
+ /* Test invalid cases */
+ for (i = 0; i < num_invalid_tests; i++) {
+ char name[100];
+
+ sprintf(name, "invalid test case: %s", invalid_tests_inputs[i]);
+
+ ret = utils_parse_time_suffix(invalid_tests_inputs[i], &result);
+ ok(ret != 0, name);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ plan_tests(num_valid_tests + num_invalid_tests);
+
+ diag("utils_parse_time_suffix tests");
+
+ test_utils_parse_time_suffix();
+
+ return exit_status();
+}
+++ /dev/null
-/*
- * Copyright 2019 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <tap/tap.h>
-
-#include "common/uuid.h"
-
-#define NR_TESTS 21
-
-static const char valid_str_1[] = "3d260c88-75ea-47b8-a7e2-d6077c0378d9";
-static const char valid_str_2[] = "611cf3a6-a68b-4515-834f-208bc2762592";
-static const char valid_str_3[] = "1b4855cc-96de-4ae8-abe3-86449c2a43c4";
-static const char valid_str_4[] = "8ADED5B9-ACD2-439F-A60C-897403AA2AB4";
-static const char valid_str_5[] = "f109e0a2-C619-4d18-b760-20EA20E0F69A";
-
-static lttng_uuid valid_uuid_1 = {
- 0x3d, 0x26, 0x0c, 0x88, 0x75, 0xea, 0x47, 0xb8,
- 0xa7, 0xe2, 0xd6, 0x07, 0x7c, 0x03, 0x78, 0xd9
-};
-static lttng_uuid valid_uuid_2 = {
- 0x61, 0x1c, 0xf3, 0xa6, 0xa6, 0x8b, 0x45, 0x15,
- 0x83, 0x4f, 0x20, 0x8b, 0xc2, 0x76, 0x25, 0x92
-};
-static lttng_uuid valid_uuid_3 = {
- 0x1b, 0x48, 0x55, 0xcc, 0x96, 0xde, 0x4a, 0xe8,
- 0xab, 0xe3, 0x86, 0x44, 0x9c, 0x2a, 0x43, 0xc4
-};
-
-static const char invalid_str_1[] = "1b485!cc-96de-4XX8-abe3-86449c2a43?4";
-static const char invalid_str_2[] = "c2e6eddb&3955&4006&be3a&70bb63bd5f25";
-static const char invalid_str_3[] = "81b1cb88-ff42-45b9-ba4d-964088ee45";
-static const char invalid_str_4[] = "2d-6c6d756574-470e-9142-a4e6ad03f143";
-static const char invalid_str_5[] = "4542ad19-9e4f-4931-8261-2101c3e089ae7";
-static const char invalid_str_6[] = "XX0123";
-
-static
-void run_test_lttng_uuid_from_str(void)
-{
- int ret;
- lttng_uuid uuid1;
-
- /*
- * Parse valid UUID strings, expect success.
- */
- ret = lttng_uuid_from_str(valid_str_1, uuid1);
- ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_1);
-
- ret = lttng_uuid_from_str(valid_str_2, uuid1);
- ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_2);
-
- ret = lttng_uuid_from_str(valid_str_3, uuid1);
- ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_3);
-
- ret = lttng_uuid_from_str(valid_str_4, uuid1);
- ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_4);
-
- ret = lttng_uuid_from_str(valid_str_5, uuid1);
- ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_5);
-
- /*
- * Parse invalid UUID strings, expect failure.
- */
- ret = lttng_uuid_from_str(invalid_str_1, uuid1);
- ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_1);
-
- ret = lttng_uuid_from_str(invalid_str_2, uuid1);
- ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_2);
-
- ret = lttng_uuid_from_str(invalid_str_3, uuid1);
- ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_3);
-
- ret = lttng_uuid_from_str(invalid_str_4, uuid1);
- ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_4);
-
- ret = lttng_uuid_from_str(invalid_str_5, uuid1);
- ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_5);
-
- ret = lttng_uuid_from_str(invalid_str_6, uuid1);
- ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_6);
-}
-
-static
-void run_test_lttng_uuid_to_str(void)
-{
- char uuid_str[LTTNG_UUID_STR_LEN];
-
- lttng_uuid_to_str(valid_uuid_1, uuid_str);
- ok(strcmp(uuid_str, valid_str_1) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_1);
-
- lttng_uuid_to_str(valid_uuid_2, uuid_str);
- ok(strcmp(uuid_str, valid_str_2) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_2);
-
- lttng_uuid_to_str(valid_uuid_3, uuid_str);
- ok(strcmp(uuid_str, valid_str_3) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_3);
-}
-
-static
-void run_test_lttng_uuid_is_equal(void)
-{
- int ret;
- lttng_uuid uuid1, uuid2;
-
- lttng_uuid_from_str(valid_str_1, uuid1);
- lttng_uuid_from_str(valid_str_1, uuid2);
- ret = lttng_uuid_is_equal(uuid1, uuid2);
- ok(ret == true, "lttng_uuid_is_equal - Compare same UUID, expect success");
-
- lttng_uuid_from_str(valid_str_2, uuid2);
- ret = lttng_uuid_is_equal(uuid1, uuid2);
- ok(ret == false, "lttng_uuid_is_equal - Compare different UUID, expect failure");
-}
-
-static
-void run_test_lttng_uuid_copy(void)
-{
- int ret;
- lttng_uuid uuid1;
-
- lttng_uuid_copy(uuid1, valid_uuid_1);
- ret = lttng_uuid_is_equal(uuid1, valid_uuid_1);
-
- ok(ret == true, "lttng_uuid_copy - Compare copied UUID with source, expect success");
-}
-
-static
-void run_test_lttng_uuid_generate(void)
-{
- int ret;
- lttng_uuid uuid1, uuid2;
-
- lttng_uuid_generate(uuid1);
- lttng_uuid_generate(uuid2);
-
- ok(lttng_uuid_is_equal(uuid1, uuid2) == false, "lttng_uuid_generate - Generated UUIDs are different");
-
- /*
- * Set the two most significant bits (bits 6 and 7) of the
- * clock_seq_hi_and_reserved to zero and one, respectively.
- */
- ret = uuid1[8] & (1 << 6);
- ok(ret == 0, "lttng_uuid_generate - bit 6 of clock_seq_hi_and_reserved is set to zero");
-
- ret = uuid1[8] & (1 << 7);
- ok(ret != 0, "lttng_uuid_generate - bit 7 of clock_seq_hi_and_reserved is set to one");
-
- /*
- * Set the four most significant bits (bits 12 through 15) of the
- * time_hi_and_version field to the 4-bit version number from
- * Section 4.1.3.
- */
- ret = uuid1[6] >> 4;
- ok(ret == LTTNG_UUID_VER, "lttng_uuid_generate - Generated UUID version check");
-}
-
-static
-void run_test(void)
-{
- plan_tests(NR_TESTS);
-
- run_test_lttng_uuid_from_str();
- run_test_lttng_uuid_to_str();
- run_test_lttng_uuid_is_equal();
- run_test_lttng_uuid_copy();
- run_test_lttng_uuid_generate();
-}
-
-int main(int argc, char **argv)
-{
- /* Run tap-formated tests */
- run_test();
-
- return exit_status();
-}
--- /dev/null
+/*
+ * Copyright 2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <tap/tap.h>
+
+#include "common/uuid.h"
+
+#define NR_TESTS 21
+
+static const char valid_str_1[] = "3d260c88-75ea-47b8-a7e2-d6077c0378d9";
+static const char valid_str_2[] = "611cf3a6-a68b-4515-834f-208bc2762592";
+static const char valid_str_3[] = "1b4855cc-96de-4ae8-abe3-86449c2a43c4";
+static const char valid_str_4[] = "8ADED5B9-ACD2-439F-A60C-897403AA2AB4";
+static const char valid_str_5[] = "f109e0a2-C619-4d18-b760-20EA20E0F69A";
+
+static lttng_uuid valid_uuid_1 = {
+ 0x3d, 0x26, 0x0c, 0x88, 0x75, 0xea, 0x47, 0xb8,
+ 0xa7, 0xe2, 0xd6, 0x07, 0x7c, 0x03, 0x78, 0xd9
+};
+static lttng_uuid valid_uuid_2 = {
+ 0x61, 0x1c, 0xf3, 0xa6, 0xa6, 0x8b, 0x45, 0x15,
+ 0x83, 0x4f, 0x20, 0x8b, 0xc2, 0x76, 0x25, 0x92
+};
+static lttng_uuid valid_uuid_3 = {
+ 0x1b, 0x48, 0x55, 0xcc, 0x96, 0xde, 0x4a, 0xe8,
+ 0xab, 0xe3, 0x86, 0x44, 0x9c, 0x2a, 0x43, 0xc4
+};
+
+static const char invalid_str_1[] = "1b485!cc-96de-4XX8-abe3-86449c2a43?4";
+static const char invalid_str_2[] = "c2e6eddb&3955&4006&be3a&70bb63bd5f25";
+static const char invalid_str_3[] = "81b1cb88-ff42-45b9-ba4d-964088ee45";
+static const char invalid_str_4[] = "2d-6c6d756574-470e-9142-a4e6ad03f143";
+static const char invalid_str_5[] = "4542ad19-9e4f-4931-8261-2101c3e089ae7";
+static const char invalid_str_6[] = "XX0123";
+
+static
+void run_test_lttng_uuid_from_str(void)
+{
+ int ret;
+ lttng_uuid uuid1;
+
+ /*
+ * Parse valid UUID strings, expect success.
+ */
+ ret = lttng_uuid_from_str(valid_str_1, uuid1);
+ ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_1);
+
+ ret = lttng_uuid_from_str(valid_str_2, uuid1);
+ ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_2);
+
+ ret = lttng_uuid_from_str(valid_str_3, uuid1);
+ ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_3);
+
+ ret = lttng_uuid_from_str(valid_str_4, uuid1);
+ ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_4);
+
+ ret = lttng_uuid_from_str(valid_str_5, uuid1);
+ ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_5);
+
+ /*
+ * Parse invalid UUID strings, expect failure.
+ */
+ ret = lttng_uuid_from_str(invalid_str_1, uuid1);
+ ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_1);
+
+ ret = lttng_uuid_from_str(invalid_str_2, uuid1);
+ ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_2);
+
+ ret = lttng_uuid_from_str(invalid_str_3, uuid1);
+ ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_3);
+
+ ret = lttng_uuid_from_str(invalid_str_4, uuid1);
+ ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_4);
+
+ ret = lttng_uuid_from_str(invalid_str_5, uuid1);
+ ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_5);
+
+ ret = lttng_uuid_from_str(invalid_str_6, uuid1);
+ ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_6);
+}
+
+static
+void run_test_lttng_uuid_to_str(void)
+{
+ char uuid_str[LTTNG_UUID_STR_LEN];
+
+ lttng_uuid_to_str(valid_uuid_1, uuid_str);
+ ok(strcmp(uuid_str, valid_str_1) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_1);
+
+ lttng_uuid_to_str(valid_uuid_2, uuid_str);
+ ok(strcmp(uuid_str, valid_str_2) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_2);
+
+ lttng_uuid_to_str(valid_uuid_3, uuid_str);
+ ok(strcmp(uuid_str, valid_str_3) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_3);
+}
+
+static
+void run_test_lttng_uuid_is_equal(void)
+{
+ int ret;
+ lttng_uuid uuid1, uuid2;
+
+ lttng_uuid_from_str(valid_str_1, uuid1);
+ lttng_uuid_from_str(valid_str_1, uuid2);
+ ret = lttng_uuid_is_equal(uuid1, uuid2);
+ ok(ret == true, "lttng_uuid_is_equal - Compare same UUID, expect success");
+
+ lttng_uuid_from_str(valid_str_2, uuid2);
+ ret = lttng_uuid_is_equal(uuid1, uuid2);
+ ok(ret == false, "lttng_uuid_is_equal - Compare different UUID, expect failure");
+}
+
+static
+void run_test_lttng_uuid_copy(void)
+{
+ int ret;
+ lttng_uuid uuid1;
+
+ lttng_uuid_copy(uuid1, valid_uuid_1);
+ ret = lttng_uuid_is_equal(uuid1, valid_uuid_1);
+
+ ok(ret == true, "lttng_uuid_copy - Compare copied UUID with source, expect success");
+}
+
+static
+void run_test_lttng_uuid_generate(void)
+{
+ int ret;
+ lttng_uuid uuid1, uuid2;
+
+ lttng_uuid_generate(uuid1);
+ lttng_uuid_generate(uuid2);
+
+ ok(lttng_uuid_is_equal(uuid1, uuid2) == false, "lttng_uuid_generate - Generated UUIDs are different");
+
+ /*
+ * Set the two most significant bits (bits 6 and 7) of the
+ * clock_seq_hi_and_reserved to zero and one, respectively.
+ */
+ ret = uuid1[8] & (1 << 6);
+ ok(ret == 0, "lttng_uuid_generate - bit 6 of clock_seq_hi_and_reserved is set to zero");
+
+ ret = uuid1[8] & (1 << 7);
+ ok(ret != 0, "lttng_uuid_generate - bit 7 of clock_seq_hi_and_reserved is set to one");
+
+ /*
+ * Set the four most significant bits (bits 12 through 15) of the
+ * time_hi_and_version field to the 4-bit version number from
+ * Section 4.1.3.
+ */
+ ret = uuid1[6] >> 4;
+ ok(ret == LTTNG_UUID_VER, "lttng_uuid_generate - Generated UUID version check");
+}
+
+static
+void run_test(void)
+{
+ plan_tests(NR_TESTS);
+
+ run_test_lttng_uuid_from_str();
+ run_test_lttng_uuid_to_str();
+ run_test_lttng_uuid_is_equal();
+ run_test_lttng_uuid_copy();
+ run_test_lttng_uuid_generate();
+}
+
+int main(int argc, char **argv)
+{
+ /* Run tap-formated tests */
+ run_test();
+
+ return exit_status();
+}