xref: /linux/tools/perf/tests/time-utils-test.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <linux/time64.h>
4 #include <inttypes.h>
5 #include <string.h>
6 #include "time-utils.h"
7 #include "evlist.h"
8 #include "session.h"
9 #include "debug.h"
10 #include "tests.h"
11 
12 static bool test__parse_nsec_time(const char *str, u64 expected)
13 {
14 	u64 ptime;
15 	int err;
16 
17 	pr_debug("\nparse_nsec_time(\"%s\")\n", str);
18 
19 	err = parse_nsec_time(str, &ptime);
20 	if (err) {
21 		pr_debug("error %d\n", err);
22 		return false;
23 	}
24 
25 	if (ptime != expected) {
26 		pr_debug("Failed. ptime %" PRIu64 " expected %" PRIu64 "\n",
27 			 ptime, expected);
28 		return false;
29 	}
30 
31 	pr_debug("%" PRIu64 "\n", ptime);
32 
33 	return true;
34 }
35 
36 static bool test__perf_time__parse_str(const char *ostr, u64 start, u64 end)
37 {
38 	struct perf_time_interval ptime;
39 	int err;
40 
41 	pr_debug("\nperf_time__parse_str(\"%s\")\n", ostr);
42 
43 	err = perf_time__parse_str(&ptime, ostr);
44 	if (err) {
45 		pr_debug("Error %d\n", err);
46 		return false;
47 	}
48 
49 	if (ptime.start != start || ptime.end != end) {
50 		pr_debug("Failed. Expected %" PRIu64 " to %" PRIu64 "\n",
51 			 start, end);
52 		return false;
53 	}
54 
55 	return true;
56 }
57 
58 #define TEST_MAX 64
59 
60 struct test_data {
61 	const char *str;
62 	u64 first;
63 	u64 last;
64 	struct perf_time_interval ptime[TEST_MAX];
65 	int num;
66 	u64 skip[TEST_MAX];
67 	u64 noskip[TEST_MAX];
68 };
69 
70 static bool test__perf_time__parse_for_ranges(struct test_data *d)
71 {
72 	struct evlist *evlist = evlist__new();
73 	struct perf_session session = { .evlist = evlist };
74 	struct perf_time_interval *ptime = NULL;
75 	int range_size, range_num;
76 	bool pass = false;
77 	int i, err;
78 
79 	if (!evlist) {
80 		pr_debug("Missing evlist\n");
81 		return false;
82 	}
83 	evlist__set_first_sample_time(evlist, d->first);
84 	evlist__set_last_sample_time(evlist, d->last);
85 	pr_debug("\nperf_time__parse_for_ranges(\"%s\")\n", d->str);
86 
87 	if (strchr(d->str, '%'))
88 		pr_debug("first_sample_time %" PRIu64 " last_sample_time %" PRIu64 "\n",
89 			 d->first, d->last);
90 
91 	err = perf_time__parse_for_ranges(d->str, &session, &ptime, &range_size,
92 					  &range_num);
93 	if (err) {
94 		pr_debug("error %d\n", err);
95 		goto out;
96 	}
97 
98 	if (range_size < d->num || range_num != d->num) {
99 		pr_debug("bad size: range_size %d range_num %d expected num %d\n",
100 			 range_size, range_num, d->num);
101 		goto out;
102 	}
103 
104 	for (i = 0; i < d->num; i++) {
105 		if (ptime[i].start != d->ptime[i].start ||
106 		    ptime[i].end != d->ptime[i].end) {
107 			pr_debug("bad range %d expected %" PRIu64 " to %" PRIu64 "\n",
108 				 i, d->ptime[i].start, d->ptime[i].end);
109 			goto out;
110 		}
111 	}
112 
113 	if (perf_time__ranges_skip_sample(ptime, d->num, 0)) {
114 		pr_debug("failed to keep 0\n");
115 		goto out;
116 	}
117 
118 	for (i = 0; i < TEST_MAX; i++) {
119 		if (d->skip[i] &&
120 		    !perf_time__ranges_skip_sample(ptime, d->num, d->skip[i])) {
121 			pr_debug("failed to skip %" PRIu64 "\n", d->skip[i]);
122 			goto out;
123 		}
124 		if (d->noskip[i] &&
125 		    perf_time__ranges_skip_sample(ptime, d->num, d->noskip[i])) {
126 			pr_debug("failed to keep %" PRIu64 "\n", d->noskip[i]);
127 			goto out;
128 		}
129 	}
130 
131 	pass = true;
132 out:
133 	evlist__put(evlist);
134 	free(ptime);
135 	return pass;
136 }
137 
138 static int test__time_utils(struct test_suite *t __maybe_unused, int subtest __maybe_unused)
139 {
140 	bool pass = true;
141 
142 	pass &= test__parse_nsec_time("0", 0);
143 	pass &= test__parse_nsec_time("1", 1000000000ULL);
144 	pass &= test__parse_nsec_time("0.000000001", 1);
145 	pass &= test__parse_nsec_time("1.000000001", 1000000001ULL);
146 	pass &= test__parse_nsec_time("123456.123456", 123456123456000ULL);
147 	pass &= test__parse_nsec_time("1234567.123456789", 1234567123456789ULL);
148 	pass &= test__parse_nsec_time("18446744073.709551615",
149 				      0xFFFFFFFFFFFFFFFFULL);
150 
151 	pass &= test__perf_time__parse_str("1234567.123456789,1234567.123456789",
152 					   1234567123456789ULL, 1234567123456789ULL);
153 	pass &= test__perf_time__parse_str("1234567.123456789,1234567.123456790",
154 					   1234567123456789ULL, 1234567123456790ULL);
155 	pass &= test__perf_time__parse_str("1234567.123456789,",
156 					   1234567123456789ULL, 0);
157 	pass &= test__perf_time__parse_str(",1234567.123456789",
158 					   0, 1234567123456789ULL);
159 	pass &= test__perf_time__parse_str("0,1234567.123456789",
160 					   0, 1234567123456789ULL);
161 
162 	{
163 		u64 b = 1234567123456789ULL;
164 		struct test_data d = {
165 			.str   = "1234567.123456789,1234567.123456790",
166 			.ptime = { {b, b + 1}, },
167 			.num = 1,
168 			.skip = { b - 1, b + 2, },
169 			.noskip = { b, b + 1, },
170 		};
171 
172 		pass &= test__perf_time__parse_for_ranges(&d);
173 	}
174 
175 	{
176 		u64 b = 1234567123456789ULL;
177 		u64 c = 7654321987654321ULL;
178 		u64 e = 8000000000000000ULL;
179 		struct test_data d = {
180 			.str   = "1234567.123456789,1234567.123456790 "
181 				 "7654321.987654321,7654321.987654444 "
182 				 "8000000,8000000.000000005",
183 			.ptime = { {b, b + 1}, {c, c + 123}, {e, e + 5}, },
184 			.num = 3,
185 			.skip = { b - 1, b + 2, c - 1, c + 124, e - 1, e + 6 },
186 			.noskip = { b, b + 1, c, c + 123, e, e + 5 },
187 		};
188 
189 		pass &= test__perf_time__parse_for_ranges(&d);
190 	}
191 
192 	{
193 		u64 b = 7654321ULL * NSEC_PER_SEC;
194 		struct test_data d = {
195 			.str    = "10%/1",
196 			.first  = b,
197 			.last   = b + 100,
198 			.ptime  = { {b, b + 9}, },
199 			.num    = 1,
200 			.skip   = { b - 1, b + 10, },
201 			.noskip = { b, b + 9, },
202 		};
203 
204 		pass &= test__perf_time__parse_for_ranges(&d);
205 	}
206 
207 	{
208 		u64 b = 7654321ULL * NSEC_PER_SEC;
209 		struct test_data d = {
210 			.str    = "10%/2",
211 			.first  = b,
212 			.last   = b + 100,
213 			.ptime  = { {b + 10, b + 19}, },
214 			.num    = 1,
215 			.skip   = { b + 9, b + 20, },
216 			.noskip = { b + 10, b + 19, },
217 		};
218 
219 		pass &= test__perf_time__parse_for_ranges(&d);
220 	}
221 
222 	{
223 		u64 b = 11223344ULL * NSEC_PER_SEC;
224 		struct test_data d = {
225 			.str    = "10%/1,10%/2",
226 			.first  = b,
227 			.last   = b + 100,
228 			.ptime  = { {b, b + 9}, {b + 10, b + 19}, },
229 			.num    = 2,
230 			.skip   = { b - 1, b + 20, },
231 			.noskip = { b, b + 8, b + 9, b + 10, b + 11, b + 12, b + 19, },
232 		};
233 
234 		pass &= test__perf_time__parse_for_ranges(&d);
235 	}
236 
237 	{
238 		u64 b = 11223344ULL * NSEC_PER_SEC;
239 		struct test_data d = {
240 			.str    = "10%/1,10%/3,10%/10",
241 			.first  = b,
242 			.last   = b + 100,
243 			.ptime  = { {b, b + 9}, {b + 20, b + 29}, { b + 90, b + 100}, },
244 			.num    = 3,
245 			.skip   = { b - 1, b + 10, b + 19, b + 30, b + 89, b + 101 },
246 			.noskip = { b, b + 9, b + 20, b + 29, b + 90, b + 100},
247 		};
248 
249 		pass &= test__perf_time__parse_for_ranges(&d);
250 	}
251 
252 	pr_debug("\n");
253 
254 	return pass ? 0 : TEST_FAIL;
255 }
256 
257 DEFINE_SUITE("time utils", time_utils);
258