root/tools/testing/selftests/user_events/user_events_selftests.h
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef _USER_EVENTS_SELFTESTS_H
#define _USER_EVENTS_SELFTESTS_H

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <unistd.h>
#include <errno.h>

#include "kselftest.h"

static inline void tracefs_unmount(void)
{
        umount("/sys/kernel/tracing");
}

static inline bool tracefs_enabled(char **message, bool *fail, bool *umount)
{
        struct stat buf;
        int ret;

        *message = "";
        *fail = false;
        *umount = false;

        /* Ensure tracefs is installed */
        ret = stat("/sys/kernel/tracing", &buf);

        if (ret == -1) {
                *message = "Tracefs is not installed";
                return false;
        }

        /* Ensure mounted tracefs */
        ret = stat("/sys/kernel/tracing/README", &buf);

        if (ret == -1 && errno == ENOENT) {
                if (mount(NULL, "/sys/kernel/tracing", "tracefs", 0, NULL) != 0) {
                        *message = "Cannot mount tracefs";
                        *fail = true;
                        return false;
                }

                *umount = true;

                ret = stat("/sys/kernel/tracing/README", &buf);
        }

        if (ret == -1) {
                *message = "Cannot access tracefs";
                *fail = true;
                return false;
        }

        return true;
}

static inline bool user_events_enabled(char **message, bool *fail, bool *umount)
{
        struct stat buf;
        int ret;

        *message = "";
        *fail = false;
        *umount = false;

        if (getuid() != 0) {
                *message = "Must be run as root";
                *fail = true;
                return false;
        }

        if (!tracefs_enabled(message, fail, umount))
                return false;

        /* Ensure user_events is installed */
        ret = stat("/sys/kernel/tracing/user_events_data", &buf);

        if (ret == -1) {
                switch (errno) {
                case ENOENT:
                        *message = "user_events is not installed";
                        return false;

                default:
                        *message = "Cannot access user_events_data";
                        *fail = true;
                        return false;
                }
        }

        return true;
}

#define USER_EVENT_FIXTURE_SETUP(statement, umount) do { \
        char *message; \
        bool fail; \
        if (!user_events_enabled(&message, &fail, &(umount))) { \
                if (fail) { \
                        TH_LOG("Setup failed due to: %s", message); \
                        ASSERT_FALSE(fail); \
                } \
                SKIP(statement, "Skipping due to: %s", message); \
        } \
} while (0)

#define USER_EVENT_FIXTURE_TEARDOWN(umount) do { \
        if ((umount))  \
                tracefs_unmount(); \
} while (0)

#endif /* _USER_EVENTS_SELFTESTS_H */