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 = { 73 .first_sample_time = d->first, 74 .last_sample_time = d->last, 75 }; 76 struct perf_session session = { .evlist = &evlist }; 77 struct perf_time_interval *ptime = NULL; 78 int range_size, range_num; 79 bool pass = false; 80 int i, err; 81 82 pr_debug("\nperf_time__parse_for_ranges(\"%s\")\n", d->str); 83 84 if (strchr(d->str, '%')) 85 pr_debug("first_sample_time %" PRIu64 " last_sample_time %" PRIu64 "\n", 86 d->first, d->last); 87 88 err = perf_time__parse_for_ranges(d->str, &session, &ptime, &range_size, 89 &range_num); 90 if (err) { 91 pr_debug("error %d\n", err); 92 goto out; 93 } 94 95 if (range_size < d->num || range_num != d->num) { 96 pr_debug("bad size: range_size %d range_num %d expected num %d\n", 97 range_size, range_num, d->num); 98 goto out; 99 } 100 101 for (i = 0; i < d->num; i++) { 102 if (ptime[i].start != d->ptime[i].start || 103 ptime[i].end != d->ptime[i].end) { 104 pr_debug("bad range %d expected %" PRIu64 " to %" PRIu64 "\n", 105 i, d->ptime[i].start, d->ptime[i].end); 106 goto out; 107 } 108 } 109 110 if (perf_time__ranges_skip_sample(ptime, d->num, 0)) { 111 pr_debug("failed to keep 0\n"); 112 goto out; 113 } 114 115 for (i = 0; i < TEST_MAX; i++) { 116 if (d->skip[i] && 117 !perf_time__ranges_skip_sample(ptime, d->num, d->skip[i])) { 118 pr_debug("failed to skip %" PRIu64 "\n", d->skip[i]); 119 goto out; 120 } 121 if (d->noskip[i] && 122 perf_time__ranges_skip_sample(ptime, d->num, d->noskip[i])) { 123 pr_debug("failed to keep %" PRIu64 "\n", d->noskip[i]); 124 goto out; 125 } 126 } 127 128 pass = true; 129 out: 130 free(ptime); 131 return pass; 132 } 133 134 int test__time_utils(struct test *t __maybe_unused, int subtest __maybe_unused) 135 { 136 bool pass = true; 137 138 pass &= test__parse_nsec_time("0", 0); 139 pass &= test__parse_nsec_time("1", 1000000000ULL); 140 pass &= test__parse_nsec_time("0.000000001", 1); 141 pass &= test__parse_nsec_time("1.000000001", 1000000001ULL); 142 pass &= test__parse_nsec_time("123456.123456", 123456123456000ULL); 143 pass &= test__parse_nsec_time("1234567.123456789", 1234567123456789ULL); 144 pass &= test__parse_nsec_time("18446744073.709551615", 145 0xFFFFFFFFFFFFFFFFULL); 146 147 pass &= test__perf_time__parse_str("1234567.123456789,1234567.123456789", 148 1234567123456789ULL, 1234567123456789ULL); 149 pass &= test__perf_time__parse_str("1234567.123456789,1234567.123456790", 150 1234567123456789ULL, 1234567123456790ULL); 151 pass &= test__perf_time__parse_str("1234567.123456789,", 152 1234567123456789ULL, 0); 153 pass &= test__perf_time__parse_str(",1234567.123456789", 154 0, 1234567123456789ULL); 155 pass &= test__perf_time__parse_str("0,1234567.123456789", 156 0, 1234567123456789ULL); 157 158 { 159 u64 b = 1234567123456789ULL; 160 struct test_data d = { 161 .str = "1234567.123456789,1234567.123456790", 162 .ptime = { {b, b + 1}, }, 163 .num = 1, 164 .skip = { b - 1, b + 2, }, 165 .noskip = { b, b + 1, }, 166 }; 167 168 pass &= test__perf_time__parse_for_ranges(&d); 169 } 170 171 { 172 u64 b = 1234567123456789ULL; 173 u64 c = 7654321987654321ULL; 174 u64 e = 8000000000000000ULL; 175 struct test_data d = { 176 .str = "1234567.123456789,1234567.123456790 " 177 "7654321.987654321,7654321.987654444 " 178 "8000000,8000000.000000005", 179 .ptime = { {b, b + 1}, {c, c + 123}, {e, e + 5}, }, 180 .num = 3, 181 .skip = { b - 1, b + 2, c - 1, c + 124, e - 1, e + 6 }, 182 .noskip = { b, b + 1, c, c + 123, e, e + 5 }, 183 }; 184 185 pass &= test__perf_time__parse_for_ranges(&d); 186 } 187 188 { 189 u64 b = 7654321ULL * NSEC_PER_SEC; 190 struct test_data d = { 191 .str = "10%/1", 192 .first = b, 193 .last = b + 100, 194 .ptime = { {b, b + 9}, }, 195 .num = 1, 196 .skip = { b - 1, b + 10, }, 197 .noskip = { b, b + 9, }, 198 }; 199 200 pass &= test__perf_time__parse_for_ranges(&d); 201 } 202 203 { 204 u64 b = 7654321ULL * NSEC_PER_SEC; 205 struct test_data d = { 206 .str = "10%/2", 207 .first = b, 208 .last = b + 100, 209 .ptime = { {b + 10, b + 19}, }, 210 .num = 1, 211 .skip = { b + 9, b + 20, }, 212 .noskip = { b + 10, b + 19, }, 213 }; 214 215 pass &= test__perf_time__parse_for_ranges(&d); 216 } 217 218 { 219 u64 b = 11223344ULL * NSEC_PER_SEC; 220 struct test_data d = { 221 .str = "10%/1,10%/2", 222 .first = b, 223 .last = b + 100, 224 .ptime = { {b, b + 9}, {b + 10, b + 19}, }, 225 .num = 2, 226 .skip = { b - 1, b + 20, }, 227 .noskip = { b, b + 8, b + 9, b + 10, b + 11, b + 12, b + 19, }, 228 }; 229 230 pass &= test__perf_time__parse_for_ranges(&d); 231 } 232 233 { 234 u64 b = 11223344ULL * NSEC_PER_SEC; 235 struct test_data d = { 236 .str = "10%/1,10%/3,10%/10", 237 .first = b, 238 .last = b + 100, 239 .ptime = { {b, b + 9}, {b + 20, b + 29}, { b + 90, b + 100}, }, 240 .num = 3, 241 .skip = { b - 1, b + 10, b + 19, b + 30, b + 89, b + 101 }, 242 .noskip = { b, b + 9, b + 20, b + 29, b + 90, b + 100}, 243 }; 244 245 pass &= test__perf_time__parse_for_ranges(&d); 246 } 247 248 pr_debug("\n"); 249 250 return pass ? 0 : TEST_FAIL; 251 } 252