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 perf_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 = 7654321ULL * NSEC_PER_SEC; 173 struct test_data d = { 174 .str = "10%/1", 175 .first = b, 176 .last = b + 100, 177 .ptime = { {b, b + 9}, }, 178 .num = 1, 179 .skip = { b - 1, b + 10, }, 180 .noskip = { b, b + 9, }, 181 }; 182 183 pass &= test__perf_time__parse_for_ranges(&d); 184 } 185 186 { 187 u64 b = 7654321ULL * NSEC_PER_SEC; 188 struct test_data d = { 189 .str = "10%/2", 190 .first = b, 191 .last = b + 100, 192 .ptime = { {b + 10, b + 19}, }, 193 .num = 1, 194 .skip = { b + 9, b + 20, }, 195 .noskip = { b + 10, b + 19, }, 196 }; 197 198 pass &= test__perf_time__parse_for_ranges(&d); 199 } 200 201 { 202 u64 b = 11223344ULL * NSEC_PER_SEC; 203 struct test_data d = { 204 .str = "10%/1,10%/2", 205 .first = b, 206 .last = b + 100, 207 .ptime = { {b, b + 9}, {b + 10, b + 19}, }, 208 .num = 2, 209 .skip = { b - 1, b + 20, }, 210 .noskip = { b, b + 8, b + 9, b + 10, b + 11, b + 12, b + 19, }, 211 }; 212 213 pass &= test__perf_time__parse_for_ranges(&d); 214 } 215 216 { 217 u64 b = 11223344ULL * NSEC_PER_SEC; 218 struct test_data d = { 219 .str = "10%/1,10%/3,10%/10", 220 .first = b, 221 .last = b + 100, 222 .ptime = { {b, b + 9}, {b + 20, b + 29}, { b + 90, b + 100}, }, 223 .num = 3, 224 .skip = { b - 1, b + 10, b + 19, b + 30, b + 89, b + 101 }, 225 .noskip = { b, b + 9, b + 20, b + 29, b + 90, b + 100}, 226 }; 227 228 pass &= test__perf_time__parse_for_ranges(&d); 229 } 230 231 pr_debug("\n"); 232 233 return pass ? 0 : TEST_FAIL; 234 } 235