summaryrefslogtreecommitdiff
path: root/kernel/trace/rv/rv_reactors_kunit.c
blob: 3850c6dda288f21dd3dc361aa045458f4d8462e4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// SPDX-License-Identifier: GPL-2.0
/*
 * KUnit tests for RV reactor registration and dispatch.
 *
 * The dispatch tests rely on reacting_on being enabled, since rv_react()
 * returns early when it is off. It is on by default when the suites run
 * built-in; as a module, re-enable it if disabled via
 * /sys/kernel/tracing/rv/reacting_on.
 */

#include <kunit/test.h>
#include <linux/build_bug.h>
#include <linux/rv.h>
#include <linux/delay.h>
#include "rv.h"

static struct rv_reactor test_reactor = {
	.name		= "kunit_test_reactor",
	.description	= "KUnit test reactor",
};

static void reactor_teardown(void *arg)
{
	rv_unregister_reactor(&test_reactor);
}

static void register_test_reactor(struct kunit *test)
{
	KUNIT_ASSERT_EQ(test, rv_register_reactor(&test_reactor), 0);
	KUNIT_ASSERT_EQ(test,
			kunit_add_action_or_reset(test, reactor_teardown, NULL), 0);
}

static void test_double_register(struct kunit *test)
{
	register_test_reactor(test);
	KUNIT_EXPECT_EQ(test, rv_register_reactor(&test_reactor), -EINVAL);
}

static const char long_reactor_name[] = "kunit_reactor_name_too_long_xxx_";
static_assert(sizeof(long_reactor_name) - 1 >= MAX_RV_REACTOR_NAME_SIZE,
	       "long_reactor_name must be at least MAX_RV_REACTOR_NAME_SIZE chars");

static void test_name_too_long(struct kunit *test)
{
	static struct rv_reactor long_reactor = {
		.name = long_reactor_name,
	};

	KUNIT_EXPECT_EQ(test, rv_register_reactor(&long_reactor), -EINVAL);
}

static struct kunit_case rv_reactor_registration_cases[] = {
	KUNIT_CASE(test_double_register),
	KUNIT_CASE(test_name_too_long),
	{}
};

static struct kunit_suite rv_reactor_registration_suite = {
	.name		= "rv_reactor_registration",
	.test_cases	= rv_reactor_registration_cases,
};

static int react_call_count;

__printf(1, 0) static void mock_react(const char *msg, va_list args)
{
	react_call_count++;
	/* Busy-wait so a timer interrupt fires inside rv_react(). */
	mdelay(20);
}

static void test_react_no_callback(struct kunit *test)
{
	struct rv_monitor monitor = {
		.name = "kunit_null_react",
	};

	react_call_count = 0;
	rv_react(&monitor, "no callback");

	KUNIT_EXPECT_EQ(test, react_call_count, 0);
}

static void test_react_callback_invoked(struct kunit *test)
{
	struct rv_monitor monitor = {
		.name	= "kunit_dispatch_monitor",
		.react	= mock_react,
	};

	react_call_count = 0;
	rv_react(&monitor, "callback invocation test");
	KUNIT_EXPECT_EQ(test, react_call_count, 1);
}

static struct kunit_case rv_react_dispatch_cases[] = {
	KUNIT_CASE(test_react_no_callback),
	KUNIT_CASE(test_react_callback_invoked),
	{}
};

static struct kunit_suite rv_react_dispatch_suite = {
	.name		= "rv_react_dispatch",
	.test_cases	= rv_react_dispatch_cases,
};

kunit_test_suites(&rv_reactor_registration_suite, &rv_react_dispatch_suite);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("KUnit tests for RV reactor registration and dispatch");