1af99e1adSBen Gardon // SPDX-License-Identifier: GPL-2.0-only
2af99e1adSBen Gardon /*
3af99e1adSBen Gardon * tools/testing/selftests/kvm/lib/test_util.c
4af99e1adSBen Gardon *
5af99e1adSBen Gardon * Copyright (C) 2020, Google LLC.
6af99e1adSBen Gardon */
71eafbd27SBen Gardon
8dfaf20afSAndrew Jones #define _GNU_SOURCE
9dfaf20afSAndrew Jones #include <stdio.h>
10dfaf20afSAndrew Jones #include <stdarg.h>
111eafbd27SBen Gardon #include <assert.h>
12af99e1adSBen Gardon #include <ctype.h>
13af99e1adSBen Gardon #include <limits.h>
141eafbd27SBen Gardon #include <stdlib.h>
151eafbd27SBen Gardon #include <time.h>
163b70c4d1SYanan Wang #include <sys/stat.h>
1720175d5eSShuah Khan #include <sys/syscall.h>
18623653b7SYanan Wang #include <linux/mman.h>
199e965bb7SBen Gardon #include "linux/kernel.h"
201eafbd27SBen Gardon
21af99e1adSBen Gardon #include "test_util.h"
22af99e1adSBen Gardon
23af99e1adSBen Gardon /*
24b31f21a7SColton Lewis * Random number generator that is usable from guest code. This is the
25b31f21a7SColton Lewis * Park-Miller LCG using standard constants.
26b31f21a7SColton Lewis */
27b31f21a7SColton Lewis
new_guest_random_state(uint32_t seed)28b31f21a7SColton Lewis struct guest_random_state new_guest_random_state(uint32_t seed)
29b31f21a7SColton Lewis {
30b31f21a7SColton Lewis struct guest_random_state s = {.seed = seed};
31b31f21a7SColton Lewis return s;
32b31f21a7SColton Lewis }
33b31f21a7SColton Lewis
guest_random_u32(struct guest_random_state * state)34b31f21a7SColton Lewis uint32_t guest_random_u32(struct guest_random_state *state)
35b31f21a7SColton Lewis {
36b31f21a7SColton Lewis state->seed = (uint64_t)state->seed * 48271 % ((uint32_t)(1 << 31) - 1);
37b31f21a7SColton Lewis return state->seed;
38b31f21a7SColton Lewis }
39b31f21a7SColton Lewis
40b31f21a7SColton Lewis /*
41af99e1adSBen Gardon * Parses "[0-9]+[kmgt]?".
42af99e1adSBen Gardon */
parse_size(const char * size)43af99e1adSBen Gardon size_t parse_size(const char *size)
44af99e1adSBen Gardon {
45af99e1adSBen Gardon size_t base;
46af99e1adSBen Gardon char *scale;
47af99e1adSBen Gardon int shift = 0;
48af99e1adSBen Gardon
49af99e1adSBen Gardon TEST_ASSERT(size && isdigit(size[0]), "Need at least one digit in '%s'", size);
50af99e1adSBen Gardon
51af99e1adSBen Gardon base = strtoull(size, &scale, 0);
52af99e1adSBen Gardon
53af99e1adSBen Gardon TEST_ASSERT(base != ULLONG_MAX, "Overflow parsing size!");
54af99e1adSBen Gardon
55af99e1adSBen Gardon switch (tolower(*scale)) {
56af99e1adSBen Gardon case 't':
57af99e1adSBen Gardon shift = 40;
58af99e1adSBen Gardon break;
59af99e1adSBen Gardon case 'g':
60af99e1adSBen Gardon shift = 30;
61af99e1adSBen Gardon break;
62af99e1adSBen Gardon case 'm':
63af99e1adSBen Gardon shift = 20;
64af99e1adSBen Gardon break;
65af99e1adSBen Gardon case 'k':
66af99e1adSBen Gardon shift = 10;
67af99e1adSBen Gardon break;
68af99e1adSBen Gardon case 'b':
69af99e1adSBen Gardon case '\0':
70af99e1adSBen Gardon shift = 0;
71af99e1adSBen Gardon break;
72af99e1adSBen Gardon default:
73af99e1adSBen Gardon TEST_ASSERT(false, "Unknown size letter %c", *scale);
74af99e1adSBen Gardon }
75af99e1adSBen Gardon
76af99e1adSBen Gardon TEST_ASSERT((base << shift) >> shift == base, "Overflow scaling size!");
77af99e1adSBen Gardon
78af99e1adSBen Gardon return base << shift;
79af99e1adSBen Gardon }
80f09205b9SBen Gardon
timespec_to_ns(struct timespec ts)81f09205b9SBen Gardon int64_t timespec_to_ns(struct timespec ts)
82f09205b9SBen Gardon {
83f09205b9SBen Gardon return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec;
84f09205b9SBen Gardon }
85f09205b9SBen Gardon
timespec_add_ns(struct timespec ts,int64_t ns)8694c4b76bSAndrew Jones struct timespec timespec_add_ns(struct timespec ts, int64_t ns)
8794c4b76bSAndrew Jones {
8894c4b76bSAndrew Jones struct timespec res;
8994c4b76bSAndrew Jones
9094c4b76bSAndrew Jones res.tv_nsec = ts.tv_nsec + ns;
91bfcaa849SAndrew Jones res.tv_sec = ts.tv_sec + res.tv_nsec / 1000000000LL;
92bfcaa849SAndrew Jones res.tv_nsec %= 1000000000LL;
9394c4b76bSAndrew Jones
9494c4b76bSAndrew Jones return res;
9594c4b76bSAndrew Jones }
9694c4b76bSAndrew Jones
timespec_add(struct timespec ts1,struct timespec ts2)97bfcaa849SAndrew Jones struct timespec timespec_add(struct timespec ts1, struct timespec ts2)
98bfcaa849SAndrew Jones {
99bfcaa849SAndrew Jones int64_t ns1 = timespec_to_ns(ts1);
100bfcaa849SAndrew Jones int64_t ns2 = timespec_to_ns(ts2);
101bfcaa849SAndrew Jones return timespec_add_ns((struct timespec){0}, ns1 + ns2);
102bfcaa849SAndrew Jones }
103bfcaa849SAndrew Jones
timespec_sub(struct timespec ts1,struct timespec ts2)104bfcaa849SAndrew Jones struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
105bfcaa849SAndrew Jones {
106bfcaa849SAndrew Jones int64_t ns1 = timespec_to_ns(ts1);
107bfcaa849SAndrew Jones int64_t ns2 = timespec_to_ns(ts2);
108bfcaa849SAndrew Jones return timespec_add_ns((struct timespec){0}, ns1 - ns2);
109bfcaa849SAndrew Jones }
110bfcaa849SAndrew Jones
timespec_elapsed(struct timespec start)111f9224a52SBen Gardon struct timespec timespec_elapsed(struct timespec start)
1121eafbd27SBen Gardon {
1131eafbd27SBen Gardon struct timespec end;
1141eafbd27SBen Gardon
1151eafbd27SBen Gardon clock_gettime(CLOCK_MONOTONIC, &end);
1161eafbd27SBen Gardon return timespec_sub(end, start);
1171eafbd27SBen Gardon }
1181eafbd27SBen Gardon
timespec_div(struct timespec ts,int divisor)1194fd94ec7SBen Gardon struct timespec timespec_div(struct timespec ts, int divisor)
1204fd94ec7SBen Gardon {
1214fd94ec7SBen Gardon int64_t ns = timespec_to_ns(ts) / divisor;
1224fd94ec7SBen Gardon
1234fd94ec7SBen Gardon return timespec_add_ns((struct timespec){0}, ns);
1244fd94ec7SBen Gardon }
1254fd94ec7SBen Gardon
print_skip(const char * fmt,...)126d0aac332SAndrew Jones void print_skip(const char *fmt, ...)
127d0aac332SAndrew Jones {
128d0aac332SAndrew Jones va_list ap;
129d0aac332SAndrew Jones
130d0aac332SAndrew Jones assert(fmt);
131d0aac332SAndrew Jones va_start(ap, fmt);
132d0aac332SAndrew Jones vprintf(fmt, ap);
133d0aac332SAndrew Jones va_end(ap);
134d0aac332SAndrew Jones puts(", skipping test");
135d0aac332SAndrew Jones }
1369e965bb7SBen Gardon
thp_configured(void)1373b70c4d1SYanan Wang bool thp_configured(void)
1383b70c4d1SYanan Wang {
1393b70c4d1SYanan Wang int ret;
1403b70c4d1SYanan Wang struct stat statbuf;
1413b70c4d1SYanan Wang
1423b70c4d1SYanan Wang ret = stat("/sys/kernel/mm/transparent_hugepage", &statbuf);
1433b70c4d1SYanan Wang TEST_ASSERT(ret == 0 || (ret == -1 && errno == ENOENT),
1443b70c4d1SYanan Wang "Error in stating /sys/kernel/mm/transparent_hugepage");
1453b70c4d1SYanan Wang
1463b70c4d1SYanan Wang return ret == 0;
1473b70c4d1SYanan Wang }
1483b70c4d1SYanan Wang
get_trans_hugepagesz(void)1493b70c4d1SYanan Wang size_t get_trans_hugepagesz(void)
1503b70c4d1SYanan Wang {
1513b70c4d1SYanan Wang size_t size;
1523b70c4d1SYanan Wang FILE *f;
1533a4f0cc6SShuah Khan int ret;
1543b70c4d1SYanan Wang
1553b70c4d1SYanan Wang TEST_ASSERT(thp_configured(), "THP is not configured in host kernel");
1563b70c4d1SYanan Wang
1573b70c4d1SYanan Wang f = fopen("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", "r");
1583b70c4d1SYanan Wang TEST_ASSERT(f != NULL, "Error in opening transparent_hugepage/hpage_pmd_size");
1593b70c4d1SYanan Wang
1603a4f0cc6SShuah Khan ret = fscanf(f, "%ld", &size);
1613a4f0cc6SShuah Khan ret = fscanf(f, "%ld", &size);
1623a4f0cc6SShuah Khan TEST_ASSERT(ret < 1, "Error reading transparent_hugepage/hpage_pmd_size");
1633b70c4d1SYanan Wang fclose(f);
1643b70c4d1SYanan Wang
1653b70c4d1SYanan Wang return size;
1663b70c4d1SYanan Wang }
1673b70c4d1SYanan Wang
get_def_hugetlb_pagesz(void)1685579fa68SYanan Wang size_t get_def_hugetlb_pagesz(void)
1695579fa68SYanan Wang {
1705579fa68SYanan Wang char buf[64];
1713dc40cf8SPaolo Bonzini const char *hugepagesize = "Hugepagesize:";
1723dc40cf8SPaolo Bonzini const char *hugepages_total = "HugePages_Total:";
1735579fa68SYanan Wang FILE *f;
1745579fa68SYanan Wang
1755579fa68SYanan Wang f = fopen("/proc/meminfo", "r");
1765579fa68SYanan Wang TEST_ASSERT(f != NULL, "Error in opening /proc/meminfo");
1775579fa68SYanan Wang
1785579fa68SYanan Wang while (fgets(buf, sizeof(buf), f) != NULL) {
1793dc40cf8SPaolo Bonzini if (strstr(buf, hugepages_total) == buf) {
1803dc40cf8SPaolo Bonzini unsigned long long total = strtoull(buf + strlen(hugepages_total), NULL, 10);
1813dc40cf8SPaolo Bonzini if (!total) {
1823dc40cf8SPaolo Bonzini fprintf(stderr, "HUGETLB is not enabled in /proc/sys/vm/nr_hugepages\n");
1833dc40cf8SPaolo Bonzini exit(KSFT_SKIP);
1843dc40cf8SPaolo Bonzini }
1853dc40cf8SPaolo Bonzini }
1863dc40cf8SPaolo Bonzini if (strstr(buf, hugepagesize) == buf) {
1875579fa68SYanan Wang fclose(f);
1883dc40cf8SPaolo Bonzini return strtoull(buf + strlen(hugepagesize), NULL, 10) << 10;
1895579fa68SYanan Wang }
1905579fa68SYanan Wang }
1915579fa68SYanan Wang
1923dc40cf8SPaolo Bonzini if (feof(f)) {
1933dc40cf8SPaolo Bonzini fprintf(stderr, "HUGETLB is not configured in host kernel");
1943dc40cf8SPaolo Bonzini exit(KSFT_SKIP);
1953dc40cf8SPaolo Bonzini }
1963dc40cf8SPaolo Bonzini
1975579fa68SYanan Wang TEST_FAIL("Error in reading /proc/meminfo");
1985579fa68SYanan Wang }
1995579fa68SYanan Wang
20095bf69b4SYanan Wang #define ANON_FLAGS (MAP_PRIVATE | MAP_ANONYMOUS)
20195bf69b4SYanan Wang #define ANON_HUGE_FLAGS (ANON_FLAGS | MAP_HUGETLB)
20295bf69b4SYanan Wang
vm_mem_backing_src_alias(uint32_t i)203623653b7SYanan Wang const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i)
204623653b7SYanan Wang {
205623653b7SYanan Wang static const struct vm_mem_backing_src_alias aliases[] = {
206623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS] = {
207623653b7SYanan Wang .name = "anonymous",
20895bf69b4SYanan Wang .flag = ANON_FLAGS,
209623653b7SYanan Wang },
210623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_THP] = {
211623653b7SYanan Wang .name = "anonymous_thp",
21295bf69b4SYanan Wang .flag = ANON_FLAGS,
213623653b7SYanan Wang },
214623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB] = {
215623653b7SYanan Wang .name = "anonymous_hugetlb",
21695bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS,
217623653b7SYanan Wang },
218623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_16KB] = {
219623653b7SYanan Wang .name = "anonymous_hugetlb_16kb",
22095bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_16KB,
221623653b7SYanan Wang },
222623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_64KB] = {
223623653b7SYanan Wang .name = "anonymous_hugetlb_64kb",
22495bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_64KB,
225623653b7SYanan Wang },
226623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_512KB] = {
227623653b7SYanan Wang .name = "anonymous_hugetlb_512kb",
22895bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_512KB,
229623653b7SYanan Wang },
230623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_1MB] = {
231623653b7SYanan Wang .name = "anonymous_hugetlb_1mb",
23295bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_1MB,
233623653b7SYanan Wang },
234623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_2MB] = {
235623653b7SYanan Wang .name = "anonymous_hugetlb_2mb",
23695bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_2MB,
237623653b7SYanan Wang },
238623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_8MB] = {
239623653b7SYanan Wang .name = "anonymous_hugetlb_8mb",
24095bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_8MB,
241623653b7SYanan Wang },
242623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_16MB] = {
243623653b7SYanan Wang .name = "anonymous_hugetlb_16mb",
24495bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_16MB,
245623653b7SYanan Wang },
246623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_32MB] = {
247623653b7SYanan Wang .name = "anonymous_hugetlb_32mb",
24895bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_32MB,
249623653b7SYanan Wang },
250623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_256MB] = {
251623653b7SYanan Wang .name = "anonymous_hugetlb_256mb",
25295bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_256MB,
253623653b7SYanan Wang },
254623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_512MB] = {
255623653b7SYanan Wang .name = "anonymous_hugetlb_512mb",
25695bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_512MB,
257623653b7SYanan Wang },
258623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_1GB] = {
259623653b7SYanan Wang .name = "anonymous_hugetlb_1gb",
26095bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_1GB,
261623653b7SYanan Wang },
262623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_2GB] = {
263623653b7SYanan Wang .name = "anonymous_hugetlb_2gb",
26495bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_2GB,
265623653b7SYanan Wang },
266623653b7SYanan Wang [VM_MEM_SRC_ANONYMOUS_HUGETLB_16GB] = {
267623653b7SYanan Wang .name = "anonymous_hugetlb_16gb",
26895bf69b4SYanan Wang .flag = ANON_HUGE_FLAGS | MAP_HUGE_16GB,
269623653b7SYanan Wang },
270c9befd59SAxel Rasmussen [VM_MEM_SRC_SHMEM] = {
271c9befd59SAxel Rasmussen .name = "shmem",
272c9befd59SAxel Rasmussen .flag = MAP_SHARED,
273c9befd59SAxel Rasmussen },
27433090a88SAxel Rasmussen [VM_MEM_SRC_SHARED_HUGETLB] = {
27533090a88SAxel Rasmussen .name = "shared_hugetlb",
27633090a88SAxel Rasmussen /*
27733090a88SAxel Rasmussen * No MAP_HUGETLB, we use MFD_HUGETLB instead. Since
27833090a88SAxel Rasmussen * we're using "file backed" memory, we need to specify
27933090a88SAxel Rasmussen * this when the FD is created, not when the area is
28033090a88SAxel Rasmussen * mapped.
28133090a88SAxel Rasmussen */
28233090a88SAxel Rasmussen .flag = MAP_SHARED,
28333090a88SAxel Rasmussen },
284623653b7SYanan Wang };
285623653b7SYanan Wang _Static_assert(ARRAY_SIZE(aliases) == NUM_SRC_TYPES,
286623653b7SYanan Wang "Missing new backing src types?");
287623653b7SYanan Wang
288623653b7SYanan Wang TEST_ASSERT(i < NUM_SRC_TYPES, "Backing src type ID %d too big", i);
289623653b7SYanan Wang
290623653b7SYanan Wang return &aliases[i];
291623653b7SYanan Wang }
292623653b7SYanan Wang
293623653b7SYanan Wang #define MAP_HUGE_PAGE_SIZE(x) (1ULL << ((x >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK))
294623653b7SYanan Wang
get_backing_src_pagesz(uint32_t i)295623653b7SYanan Wang size_t get_backing_src_pagesz(uint32_t i)
296623653b7SYanan Wang {
297623653b7SYanan Wang uint32_t flag = vm_mem_backing_src_alias(i)->flag;
298623653b7SYanan Wang
299623653b7SYanan Wang switch (i) {
300623653b7SYanan Wang case VM_MEM_SRC_ANONYMOUS:
301c9befd59SAxel Rasmussen case VM_MEM_SRC_SHMEM:
302623653b7SYanan Wang return getpagesize();
303623653b7SYanan Wang case VM_MEM_SRC_ANONYMOUS_THP:
304623653b7SYanan Wang return get_trans_hugepagesz();
305623653b7SYanan Wang case VM_MEM_SRC_ANONYMOUS_HUGETLB:
30633090a88SAxel Rasmussen case VM_MEM_SRC_SHARED_HUGETLB:
307623653b7SYanan Wang return get_def_hugetlb_pagesz();
308623653b7SYanan Wang default:
309623653b7SYanan Wang return MAP_HUGE_PAGE_SIZE(flag);
310623653b7SYanan Wang }
311623653b7SYanan Wang }
312623653b7SYanan Wang
is_backing_src_hugetlb(uint32_t i)313f4870ef3SSean Christopherson bool is_backing_src_hugetlb(uint32_t i)
314f4870ef3SSean Christopherson {
315f4870ef3SSean Christopherson return !!(vm_mem_backing_src_alias(i)->flag & MAP_HUGETLB);
316f4870ef3SSean Christopherson }
317f4870ef3SSean Christopherson
print_available_backing_src_types(const char * prefix)3189f2fc555SDavid Matlack static void print_available_backing_src_types(const char *prefix)
3199e965bb7SBen Gardon {
3209e965bb7SBen Gardon int i;
3219e965bb7SBen Gardon
3229f2fc555SDavid Matlack printf("%sAvailable backing src types:\n", prefix);
3239f2fc555SDavid Matlack
324623653b7SYanan Wang for (i = 0; i < NUM_SRC_TYPES; i++)
3259f2fc555SDavid Matlack printf("%s %s\n", prefix, vm_mem_backing_src_alias(i)->name);
3269f2fc555SDavid Matlack }
3279f2fc555SDavid Matlack
backing_src_help(const char * flag)3289f2fc555SDavid Matlack void backing_src_help(const char *flag)
3299f2fc555SDavid Matlack {
3309f2fc555SDavid Matlack printf(" %s: specify the type of memory that should be used to\n"
3319f2fc555SDavid Matlack " back the guest data region. (default: %s)\n",
3329f2fc555SDavid Matlack flag, vm_mem_backing_src_alias(DEFAULT_VM_MEM_SRC)->name);
3339f2fc555SDavid Matlack print_available_backing_src_types(" ");
3349e965bb7SBen Gardon }
3359e965bb7SBen Gardon
parse_backing_src_type(const char * type_name)3369e965bb7SBen Gardon enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name)
3379e965bb7SBen Gardon {
3389e965bb7SBen Gardon int i;
3399e965bb7SBen Gardon
340623653b7SYanan Wang for (i = 0; i < NUM_SRC_TYPES; i++)
341623653b7SYanan Wang if (!strcmp(type_name, vm_mem_backing_src_alias(i)->name))
342623653b7SYanan Wang return i;
3439e965bb7SBen Gardon
3449f2fc555SDavid Matlack print_available_backing_src_types("");
3459e965bb7SBen Gardon TEST_FAIL("Unknown backing src type: %s", type_name);
3469e965bb7SBen Gardon return -1;
3479e965bb7SBen Gardon }
34820175d5eSShuah Khan
get_run_delay(void)34920175d5eSShuah Khan long get_run_delay(void)
35020175d5eSShuah Khan {
35120175d5eSShuah Khan char path[64];
35220175d5eSShuah Khan long val[2];
35320175d5eSShuah Khan FILE *fp;
35420175d5eSShuah Khan
35520175d5eSShuah Khan sprintf(path, "/proc/%ld/schedstat", syscall(SYS_gettid));
35620175d5eSShuah Khan fp = fopen(path, "r");
357f5013d41SShuah Khan /* Return MIN_RUN_DELAY_NS upon failure just to be safe */
358f5013d41SShuah Khan if (fscanf(fp, "%ld %ld ", &val[0], &val[1]) < 2)
359f5013d41SShuah Khan val[1] = MIN_RUN_DELAY_NS;
36020175d5eSShuah Khan fclose(fp);
36120175d5eSShuah Khan
36220175d5eSShuah Khan return val[1];
36320175d5eSShuah Khan }
364018ea2d7SVipin Sharma
atoi_paranoid(const char * num_str)365018ea2d7SVipin Sharma int atoi_paranoid(const char *num_str)
366018ea2d7SVipin Sharma {
367018ea2d7SVipin Sharma char *end_ptr;
368018ea2d7SVipin Sharma long num;
369018ea2d7SVipin Sharma
370018ea2d7SVipin Sharma errno = 0;
371018ea2d7SVipin Sharma num = strtol(num_str, &end_ptr, 0);
372018ea2d7SVipin Sharma TEST_ASSERT(!errno, "strtol(\"%s\") failed", num_str);
373018ea2d7SVipin Sharma TEST_ASSERT(num_str != end_ptr,
374018ea2d7SVipin Sharma "strtol(\"%s\") didn't find a valid integer.", num_str);
375018ea2d7SVipin Sharma TEST_ASSERT(*end_ptr == '\0',
376018ea2d7SVipin Sharma "strtol(\"%s\") failed to parse trailing characters \"%s\".",
377018ea2d7SVipin Sharma num_str, end_ptr);
378018ea2d7SVipin Sharma TEST_ASSERT(num >= INT_MIN && num <= INT_MAX,
379018ea2d7SVipin Sharma "%ld not in range of [%d, %d]", num, INT_MIN, INT_MAX);
380018ea2d7SVipin Sharma
381018ea2d7SVipin Sharma return num;
382018ea2d7SVipin Sharma }
383dfaf20afSAndrew Jones
strdup_printf(const char * fmt,...)384dfaf20afSAndrew Jones char *strdup_printf(const char *fmt, ...)
385dfaf20afSAndrew Jones {
386dfaf20afSAndrew Jones va_list ap;
387dfaf20afSAndrew Jones char *str;
388dfaf20afSAndrew Jones
389dfaf20afSAndrew Jones va_start(ap, fmt);
390*7c329bbdSSean Christopherson TEST_ASSERT(vasprintf(&str, fmt, ap) >= 0, "vasprintf() failed");
391dfaf20afSAndrew Jones va_end(ap);
392dfaf20afSAndrew Jones
393dfaf20afSAndrew Jones return str;
394dfaf20afSAndrew Jones }
395