1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * DAMON Debugfs Interface Unit Tests |
4 | * |
5 | * Author: SeongJae Park <sj@kernel.org> |
6 | */ |
7 | |
8 | #ifdef CONFIG_DAMON_DBGFS_KUNIT_TEST |
9 | |
10 | #ifndef _DAMON_DBGFS_TEST_H |
11 | #define _DAMON_DBGFS_TEST_H |
12 | |
13 | #include <kunit/test.h> |
14 | |
15 | static void damon_dbgfs_test_str_to_ints(struct kunit *test) |
16 | { |
17 | char *question; |
18 | int *answers; |
19 | int expected[] = {12, 35, 46}; |
20 | ssize_t nr_integers = 0, i; |
21 | |
22 | question = "123" ; |
23 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
24 | KUNIT_EXPECT_EQ(test, (ssize_t)1, nr_integers); |
25 | KUNIT_EXPECT_EQ(test, 123, answers[0]); |
26 | kfree(objp: answers); |
27 | |
28 | question = "123abc" ; |
29 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
30 | KUNIT_EXPECT_EQ(test, (ssize_t)1, nr_integers); |
31 | KUNIT_EXPECT_EQ(test, 123, answers[0]); |
32 | kfree(objp: answers); |
33 | |
34 | question = "a123" ; |
35 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
36 | KUNIT_EXPECT_EQ(test, (ssize_t)0, nr_integers); |
37 | kfree(objp: answers); |
38 | |
39 | question = "12 35" ; |
40 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
41 | KUNIT_EXPECT_EQ(test, (ssize_t)2, nr_integers); |
42 | for (i = 0; i < nr_integers; i++) |
43 | KUNIT_EXPECT_EQ(test, expected[i], answers[i]); |
44 | kfree(objp: answers); |
45 | |
46 | question = "12 35 46" ; |
47 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
48 | KUNIT_EXPECT_EQ(test, (ssize_t)3, nr_integers); |
49 | for (i = 0; i < nr_integers; i++) |
50 | KUNIT_EXPECT_EQ(test, expected[i], answers[i]); |
51 | kfree(objp: answers); |
52 | |
53 | question = "12 35 abc 46" ; |
54 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
55 | KUNIT_EXPECT_EQ(test, (ssize_t)2, nr_integers); |
56 | for (i = 0; i < 2; i++) |
57 | KUNIT_EXPECT_EQ(test, expected[i], answers[i]); |
58 | kfree(objp: answers); |
59 | |
60 | question = "" ; |
61 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
62 | KUNIT_EXPECT_EQ(test, (ssize_t)0, nr_integers); |
63 | kfree(objp: answers); |
64 | |
65 | question = "\n" ; |
66 | answers = str_to_ints(str: question, strlen(question), nr_ints: &nr_integers); |
67 | KUNIT_EXPECT_EQ(test, (ssize_t)0, nr_integers); |
68 | kfree(objp: answers); |
69 | } |
70 | |
71 | static void damon_dbgfs_test_set_targets(struct kunit *test) |
72 | { |
73 | struct damon_ctx *ctx = dbgfs_new_ctx(); |
74 | char buf[64]; |
75 | |
76 | /* Make DAMON consider target has no pid */ |
77 | damon_select_ops(ctx, id: DAMON_OPS_PADDR); |
78 | |
79 | dbgfs_set_targets(ctx, nr_targets: 0, NULL); |
80 | sprint_target_ids(ctx, buf, len: 64); |
81 | KUNIT_EXPECT_STREQ(test, (char *)buf, "\n" ); |
82 | |
83 | dbgfs_set_targets(ctx, nr_targets: 1, NULL); |
84 | sprint_target_ids(ctx, buf, len: 64); |
85 | KUNIT_EXPECT_STREQ(test, (char *)buf, "42\n" ); |
86 | |
87 | dbgfs_set_targets(ctx, nr_targets: 0, NULL); |
88 | sprint_target_ids(ctx, buf, len: 64); |
89 | KUNIT_EXPECT_STREQ(test, (char *)buf, "\n" ); |
90 | |
91 | dbgfs_destroy_ctx(ctx); |
92 | } |
93 | |
94 | static void damon_dbgfs_test_set_init_regions(struct kunit *test) |
95 | { |
96 | struct damon_ctx *ctx = damon_new_ctx(); |
97 | /* Each line represents one region in ``<target idx> <start> <end>`` */ |
98 | char * const valid_inputs[] = {"1 10 20\n 1 20 30\n1 35 45" , |
99 | "1 10 20\n" , |
100 | "1 10 20\n0 39 59\n0 70 134\n 1 20 25\n" , |
101 | "" }; |
102 | /* Reading the file again will show sorted, clean output */ |
103 | char * const valid_expects[] = {"1 10 20\n1 20 30\n1 35 45\n" , |
104 | "1 10 20\n" , |
105 | "0 39 59\n0 70 134\n1 10 20\n1 20 25\n" , |
106 | "" }; |
107 | char * const invalid_inputs[] = {"3 10 20\n" , /* target not exists */ |
108 | "1 10 20\n 1 14 26\n" , /* regions overlap */ |
109 | "0 10 20\n1 30 40\n 0 5 8" }; /* not sorted by address */ |
110 | char *input, *expect; |
111 | int i, rc; |
112 | char buf[256]; |
113 | |
114 | damon_select_ops(ctx, id: DAMON_OPS_PADDR); |
115 | |
116 | dbgfs_set_targets(ctx, nr_targets: 3, NULL); |
117 | |
118 | /* Put valid inputs and check the results */ |
119 | for (i = 0; i < ARRAY_SIZE(valid_inputs); i++) { |
120 | input = valid_inputs[i]; |
121 | expect = valid_expects[i]; |
122 | |
123 | rc = set_init_regions(c: ctx, str: input, len: strnlen(p: input, maxlen: 256)); |
124 | KUNIT_EXPECT_EQ(test, rc, 0); |
125 | |
126 | memset(buf, 0, 256); |
127 | sprint_init_regions(c: ctx, buf, len: 256); |
128 | |
129 | KUNIT_EXPECT_STREQ(test, (char *)buf, expect); |
130 | } |
131 | /* Put invalid inputs and check the return error code */ |
132 | for (i = 0; i < ARRAY_SIZE(invalid_inputs); i++) { |
133 | input = invalid_inputs[i]; |
134 | pr_info("input: %s\n" , input); |
135 | rc = set_init_regions(c: ctx, str: input, len: strnlen(p: input, maxlen: 256)); |
136 | KUNIT_EXPECT_EQ(test, rc, -EINVAL); |
137 | |
138 | memset(buf, 0, 256); |
139 | sprint_init_regions(c: ctx, buf, len: 256); |
140 | |
141 | KUNIT_EXPECT_STREQ(test, (char *)buf, "" ); |
142 | } |
143 | |
144 | dbgfs_set_targets(ctx, nr_targets: 0, NULL); |
145 | damon_destroy_ctx(ctx); |
146 | } |
147 | |
148 | static struct kunit_case damon_test_cases[] = { |
149 | KUNIT_CASE(damon_dbgfs_test_str_to_ints), |
150 | KUNIT_CASE(damon_dbgfs_test_set_targets), |
151 | KUNIT_CASE(damon_dbgfs_test_set_init_regions), |
152 | {}, |
153 | }; |
154 | |
155 | static struct kunit_suite damon_test_suite = { |
156 | .name = "damon-dbgfs" , |
157 | .test_cases = damon_test_cases, |
158 | }; |
159 | kunit_test_suite(damon_test_suite); |
160 | |
161 | #endif /* _DAMON_TEST_H */ |
162 | |
163 | #endif /* CONFIG_DAMON_KUNIT_TEST */ |
164 | |