1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * tools/testing/selftests/kvm/lib/test_util.c 4 * 5 * Copyright (C) 2020, Google LLC. 6 */ 7 8 #include <assert.h> 9 #include <ctype.h> 10 #include <limits.h> 11 #include <stdlib.h> 12 #include <time.h> 13 14 #include "test_util.h" 15 16 /* 17 * Parses "[0-9]+[kmgt]?". 18 */ 19 size_t parse_size(const char *size) 20 { 21 size_t base; 22 char *scale; 23 int shift = 0; 24 25 TEST_ASSERT(size && isdigit(size[0]), "Need at least one digit in '%s'", size); 26 27 base = strtoull(size, &scale, 0); 28 29 TEST_ASSERT(base != ULLONG_MAX, "Overflow parsing size!"); 30 31 switch (tolower(*scale)) { 32 case 't': 33 shift = 40; 34 break; 35 case 'g': 36 shift = 30; 37 break; 38 case 'm': 39 shift = 20; 40 break; 41 case 'k': 42 shift = 10; 43 break; 44 case 'b': 45 case '\0': 46 shift = 0; 47 break; 48 default: 49 TEST_ASSERT(false, "Unknown size letter %c", *scale); 50 } 51 52 TEST_ASSERT((base << shift) >> shift == base, "Overflow scaling size!"); 53 54 return base << shift; 55 } 56 57 int64_t timespec_to_ns(struct timespec ts) 58 { 59 return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec; 60 } 61 62 struct timespec timespec_add_ns(struct timespec ts, int64_t ns) 63 { 64 struct timespec res; 65 66 res.tv_nsec = ts.tv_nsec + ns; 67 res.tv_sec = ts.tv_sec + res.tv_nsec / 1000000000LL; 68 res.tv_nsec %= 1000000000LL; 69 70 return res; 71 } 72 73 struct timespec timespec_add(struct timespec ts1, struct timespec ts2) 74 { 75 int64_t ns1 = timespec_to_ns(ts1); 76 int64_t ns2 = timespec_to_ns(ts2); 77 return timespec_add_ns((struct timespec){0}, ns1 + ns2); 78 } 79 80 struct timespec timespec_sub(struct timespec ts1, struct timespec ts2) 81 { 82 int64_t ns1 = timespec_to_ns(ts1); 83 int64_t ns2 = timespec_to_ns(ts2); 84 return timespec_add_ns((struct timespec){0}, ns1 - ns2); 85 } 86 87 struct timespec timespec_diff_now(struct timespec start) 88 { 89 struct timespec end; 90 91 clock_gettime(CLOCK_MONOTONIC, &end); 92 return timespec_sub(end, start); 93 } 94 95 struct timespec timespec_div(struct timespec ts, int divisor) 96 { 97 int64_t ns = timespec_to_ns(ts) / divisor; 98 99 return timespec_add_ns((struct timespec){0}, ns); 100 } 101 102 void print_skip(const char *fmt, ...) 103 { 104 va_list ap; 105 106 assert(fmt); 107 va_start(ap, fmt); 108 vprintf(fmt, ap); 109 va_end(ap); 110 puts(", skipping test"); 111 } 112