| /* |
| * gtests/include/test_util.h |
| * |
| * Copyright (C) 2018, Google LLC. |
| * |
| * This work is licensed under the terms of the GNU GPL, version 2. |
| * |
| */ |
| |
| #ifndef _GTESTS_TEST_UTIL_H |
| #define _GTESTS_TEST_UTIL_H |
| |
| #include <errno.h> |
| #include <regex.h> |
| #include <signal.h> /* For siginfo_t */ |
| #include <stdbool.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <time.h> /* For struct timespec */ |
| #include <unistd.h> |
| |
| #include <sys/wait.h> |
| #include <sys/types.h> |
| |
| #include <linux/capability.h> |
| #include <linux/elf.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* For portability with use of __func__. */ |
| #if __STDC_VERSION__ < 199901L |
| # if __GNUC__ >= 2 |
| # define __func__ __FUNCTION__ |
| # else |
| # define __func__ "<unknown>" |
| # endif |
| #endif |
| |
| #define TEST_UTIL_SUCCESS 0 |
| #define TEST_UTIL_SYNTAX_ERR 1 |
| #define TEST_UTIL_VALUE_ERR 2 |
| |
| #define TEST_MALLOC_PROT_BEFORE (1 << 0) |
| #define TEST_MALLOC_PROT_AFTER (1 << 1) |
| #define TEST_MALLOC_ALIGN (1 << 2) |
| #define TEST_MALLOC_ALLOW_PROT_CHG (1 << 3) |
| #define TEST_MALLOC_MMAP_FD (1 << 4) |
| #define TEST_MALLOC_MMAP_FD_OFFSET (TEST_MALLOC_MMAP_FD | (1 << 5)) |
| |
| enum test_malloc_ctl_cmd { |
| CHG_PROT, /* Change the protections of test_malloc'd memory. |
| * Memory must have been allocated with the |
| * TEST_MALLOC_PROT_CHG flag in order to use this command. */ |
| GET_FLAGS, /* Retrieve flags with which memory was test_malloc'd. */ |
| }; |
| |
| struct test_rng { |
| uint64_t low; |
| uint64_t high; /* Inclusive */ |
| }; |
| |
| struct test_symb { |
| const char *name; |
| uint64_t val; |
| }; |
| struct test_symbi { |
| const char *name; |
| int64_t val; |
| }; |
| |
| /* Wraps information retrieved from the proc/<pid>/maps |
| * file concerning a specific mapped memory address. |
| */ |
| struct test_pg_info { |
| uint64_t start; /* The starting address of the mapping, inclusive. */ |
| uint64_t end; /* The ending address of the mapping, inclusive. */ |
| size_t size; /* The size of the mapping. */ |
| int prot; /* The protections of the mapping, |
| * one or more of PROT_READ, PROT_WRITE, PROT_EXEC, |
| * or PROT_NONE as defined in sys/mman.h. */ |
| bool shared; /* Whether the mapping is shared or private. */ |
| }; |
| |
| typedef struct __user_cap_data_struct *test_cap_t; |
| typedef enum { |
| TEST_CAP_EFFECTIVE = 0x2bc0, |
| TEST_CAP_PERMITTED, |
| TEST_CAP_INHERITABLE, |
| } test_cap_group_t; |
| |
| extern const struct test_symb test_symb_infinity[]; |
| extern const struct test_symb test_known_errno[]; |
| extern const struct test_symb test_known_sig[]; |
| |
| char *test_get_opt_str(const char *arg1, char *args[]); |
| int test_parse_i64(const char *str, int64_t *val, int64_t min, |
| int64_t max, const struct test_symbi symb[]); |
| int test_parse_u32(const char *str, uint32_t *val, uint32_t max, |
| const struct test_symb symb[]); |
| int test_parse_u64(const char *str, uint64_t *val, uint64_t max, |
| const struct test_symb symb[]); |
| int test_parse_float(const char *str, float *val); |
| int test_parse_rngs(const char *str, struct test_rng **rngs, unsigned int *num, |
| uint64_t max, const struct test_symb symb[]); |
| char *test_rngs2str(const struct test_rng *rngs, unsigned int num, |
| unsigned int radix); |
| bool test_rngs_idx_isset(unsigned long long idx, const struct test_rng *rngs, |
| unsigned int num); |
| void test_rngs_idx_set(unsigned long long idx, struct test_rng **rngs, |
| unsigned int *num); |
| |
| char *test_dyn_sprintf(const char *fmt, ...); |
| /* Don't inline so we can omit from stack dumps. See test_dump_stack. */ |
| void __attribute__((noinline)) __attribute__ ((format (printf, 5, 6))) |
| test_assert(bool exp, const char *exp_str, |
| const char *file, unsigned int line, const char *fmt, ...); |
| uint32_t test_rand32(void); |
| bool test_rand_bool(void); |
| uint32_t test_rand32_mod(uint32_t mod); |
| unsigned int test_rand_choice(unsigned int num, const float weights[]); |
| |
| void test_delay(double amt); |
| void test_delay_ts(const struct timespec *amt); |
| int test_delay_until(const struct timespec *end, pid_t pid); |
| double test_ts2double(const struct timespec *val); |
| struct timespec test_double2ts(double amt); |
| |
| /* Current implementation of test_ts_delta requires *second >= *first */ |
| struct timespec test_ts_delta(const struct timespec *first, |
| const struct timespec *second); |
| void test_ts_sum(struct timespec *sum, const struct timespec *t1, |
| const struct timespec *t2); |
| /* Current implementation of test_ts_minums requires *t1 >= * t2 */ |
| void test_ts_minus(struct timespec *minus, const struct timespec *t1, |
| const struct timespec *t2); |
| int test_ts_cmp(const struct timespec *t1, const struct timespec *t2); |
| |
| char *test_debugfs_mnt_point(void); |
| void test_dump_siginfo(FILE *file, siginfo_t *sig); |
| |
| uint64_t test_tsc_freq(int cpu); |
| void test_xdump(FILE *stream, const void *buf, size_t size, |
| intptr_t addr_start, uint8_t indent); |
| |
| char *test_config_str(const char *name); |
| |
| int test_cap_get(pid_t pid, test_cap_t *cap); |
| int test_cap_set(pid_t pid, const test_cap_t *cap); |
| bool test_cap_flag_fetch(const test_cap_t *cap, test_cap_group_t group, |
| unsigned int trait); |
| void test_cap_flag_assign(test_cap_t *cap, test_cap_group_t group, |
| unsigned int trait, bool rval); |
| |
| float test_sgniff(long double expected, float actual); |
| float test_sgnif(long double expected, double actual); |
| float test_sgnifl(long double expected, long double actual); |
| |
| int test_pg_info(pid_t pid, uint64_t addr, |
| struct test_pg_info *info); |
| int test_pg_info_map(const char *map, uint64_t addr, |
| struct test_pg_info *info); |
| |
| ssize_t test_write(int fd, const void *buf, size_t count); |
| ssize_t test_read(int fd, void *buf, size_t count); |
| int test_seq_read(const char *path, char **bufp, size_t *sizep); |
| |
| void *test_malloc(size_t size, uint32_t flags, ...); |
| void test_malloc_free(void *addr); |
| void test_malloc_chg_prot(const void *addr, int prot); |
| uint32_t test_malloc_get_flags(const void *addr); |
| |
| #define TEST_ASSERT(e, fmt, ...) \ |
| test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| |
| /* Shorthand for TEST_ASSERT(e, "%s", "") */ |
| #define ASSERT(e) \ |
| TEST_ASSERT(e, "ASSERT(%s) failed.", #e) |
| |
| #define ASSERT_EQ(a, b) do { \ |
| typeof(a) __a = (a); \ |
| typeof(b) __b = (b); \ |
| TEST_ASSERT(__a == __b, \ |
| "ASSERT_EQ(%s, %s) failed.\n" \ |
| "\t%s is %#lx\n" \ |
| "\t%s is %#lx", \ |
| #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \ |
| } while (0) |
| |
| int __attribute__ ((format (printf, 1, 2))) test_printk(const char *fmt, ...); |
| |
| struct test_elfsymb { |
| uintmax_t value; |
| size_t size; |
| }; |
| void test_elfhdr_get(const char *filename, Elf64_Ehdr *hdrp); |
| int test_elfsymb_get(const char *filename, const char *name, |
| struct test_elfsymb *symbp); |
| |
| void extract_pageflags(void *addr, unsigned int count, uint64_t *buffer); |
| |
| /* Architecture dependent inline functions. |
| * |
| * For each architecutre the following inline functions are provided: |
| * |
| * void test_barrier_read(void) |
| * Delay until the current processor has completed all outstanding |
| * cache coherence read operations. |
| * |
| * void test_barrier_write(void) |
| * Delay until the current processor has completed all outstanding |
| * cache coherence write operations. |
| * |
| * void test_barrier_read_write(void) |
| * Delay until the current processor has completed all outstanding |
| * cache coherence read and write operations. |
| * |
| * void test_serialize(void) |
| * Delay until the current processor has completed all outstanding |
| * operations. At a minimum, this includes the following: |
| * |
| * + Background cache coherence read operations. |
| * + Background cache coherence write operations. |
| * + Flush instruction pipeline. |
| * |
| * uint64_t test_rdtsc(bool skip_isync) |
| * Reads the processors time-stamp counter and returns its value. |
| * Each implementation assures that instructions before reading |
| * the time-stamp counter have completed (e.g. instruction pipe-line |
| * flush), although there may be pending backgroud operations |
| * (e.g. backgroup cache-coherence operations). Note, an instruction |
| * pipe-line flush is not performed after reading the time-stamp |
| * counter, because it is assumed that there is a time-stamp counter |
| * per processor and thus it is not a shared resource, which could |
| * delay the ability to read the counter value. |
| */ |
| #if defined(__x86_64__) |
| static inline void test_barrier_read(void) |
| { |
| __asm__ __volatile__("lfence" : : : "memory"); |
| } |
| |
| static inline void test_barrier_write(void) |
| { |
| __asm__ __volatile__("sfence" : : : "memory"); |
| } |
| |
| static inline void test_barrier_read_write(void) |
| { |
| __asm__ __volatile__("mfence" : : : "memory"); |
| } |
| |
| static inline void test_serialize(void) |
| { |
| uint32_t eax, ebx, ecx, edx; |
| |
| __asm__ __volatile__ ( |
| "cpuid\n" |
| : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| : "a" (0), "c" (0) |
| : "memory" |
| ); |
| } |
| |
| static inline uint64_t test_rdtsc(void) |
| { |
| uint32_t low, high; |
| |
| asm volatile("mfence; lfence"); |
| __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)); |
| asm volatile("lfence"); |
| |
| return ((uint64_t) high << 32) | low; |
| } |
| |
| |
| #elif defined(__PPC64__) |
| |
| static inline void test_barrier_read(void) |
| { |
| __asm__ volatile ("sync" : : : "memory"); |
| } |
| |
| static inline void test_barrier_write(void) |
| { |
| __asm__ volatile ("sync" : : : "memory"); |
| } |
| |
| static inline void test_serialize(void) |
| { |
| __asm__ volatile ("sync"); |
| } |
| |
| static inline uint64_t test_rdtsc(void) |
| { |
| uint64_t upper, lower, upper_again; |
| |
| /* Can only read the upper or lower half of the time-stamp counter |
| * with a single instruction. To handle this, will read the |
| * upper half, then the lower half, then the upper half again. |
| * Will combine and return the upper and lower half only when |
| * the first and second read of the upper half return the same |
| * value. In cases where the upper half is different between |
| * the two times it is read, the whole process is repeated, until |
| * a case occurs when the two reads of the upper half return the |
| * same value. |
| */ |
| __asm__ volatile( |
| "0:\n" |
| "\tmftbu %0\n" |
| "\tmftb %1\n" |
| "\tmftbu %2\n" |
| "\tcmpw %2, %0\n" |
| "\tbne 0b\n" |
| : "=r"(upper), "=r"(lower),"=r"(upper_again) |
| ); |
| |
| return (upper << 32) | lower; |
| } |
| |
| #elif defined(__aarch64__) |
| |
| static inline void test_barrier_read(void) |
| { |
| /* "memory" to prevent compiler reordering. |
| * "dsb ld" == data synchronization barrier, full system, reads. |
| * This instruction completes after all prior memory reads issued by |
| * this CPU to any observer in the system, are complete. |
| * See ARMv8 Architecture Reference Manual sections B2.7.3 and C6.6.62. |
| */ |
| __asm__ volatile ("dsb ld" : : : "memory"); |
| } |
| |
| static inline void test_barrier_write(void) |
| { |
| /* "memory" to prevent compiler reordering. |
| * "dsb st" == data synchronization barrier, full system, writes. |
| * This instruction completes after all prior memory writes issued by |
| * this CPU are visible to all observers in the system. |
| * See ARMv8 Architecture Reference Manual sections B2.7.3 and C6.6.62. |
| */ |
| __asm__ volatile ("dsb st" : : : "memory"); |
| } |
| |
| static inline void test_serialize(void) |
| { |
| /* "memory" to prevent compiler reordering. |
| * "dsb sy" == data synchronization barrier, full system, all types. |
| * "isb sy" == instruction synchronization barrier, full system. |
| * See ARMv8 Architecture Reference Manual sections B2.7.3, C6.6.62 and |
| * C6.6.72. |
| */ |
| __asm__ volatile ( |
| "dsb sy\n\t" |
| "isb sy" |
| : : : "memory"); |
| } |
| |
| static inline uint64_t test_rdtsc(void) |
| { |
| uint64_t value; |
| |
| /* |
| * Read the virtual timer, to ensure this will work correctly within |
| * VMs as well. Note that the timer typically runs at a lower frequency |
| * than the CPU. |
| */ |
| test_serialize(); |
| __asm__ volatile("mrs %0, cntvct_el0" : "=r"(value)); |
| |
| return value; |
| } |
| |
| #else |
| #error "Unknown architecture" |
| #endif |
| |
| /* Metrics - C Language Interface |
| * |
| * Note: C++-language portion of interface described below, within |
| * "__cplusplus" portion of this header. See below, |
| * class GtestsUtilMetrics.. |
| */ |
| void metrics_post_uint64(const char *name, uint64_t value, const char *units); |
| void metrics_post_int64(const char *name, int64_t value, const char *units); |
| void metrics_post_float(const char *name, float value, const char *units); |
| void metrics_post_double(const char *name, double value, const char *units); |
| void metrics_post_uint64_array(const char *name, |
| const uint64_t *values, unsigned int num, const char *units); |
| void metrics_post_int64_array(const char *name, |
| const int64_t *values, unsigned int num, const char *units); |
| void metrics_post_float_array(const char *name, |
| const float *values, unsigned int num, const char *units); |
| void metrics_post_double_array(const char *name, |
| const double *values, unsigned int num, const char *units); |
| |
| #ifdef __cplusplus |
| } /* Closing brace for extern "C" */ |
| |
| /* Declarations for C++ only. */ |
| #include <iostream> |
| #include <mutex> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| const unsigned int GtestsUtil_Magic001 = 0x3a40; |
| |
| std::string StringPrintf(const char* format, ...); |
| |
| class GtestsUtil_Log { |
| public: |
| static const unsigned int magic001 = 0x3a40; |
| |
| enum LogSeverity { |
| INFO = magic001, |
| WARNING, |
| ERROR, |
| FATAL, |
| }; |
| |
| GtestsUtil_Log(const char* file, unsigned int line, |
| enum LogSeverity severity); |
| ~GtestsUtil_Log(); |
| |
| template <typename T> GtestsUtil_Log& operator<<(const T& v) { |
| /* Right-hand-side operand is inserted to the string_ |
| * variable, instead of directly to the stream, so |
| * that the current state of std::cout and std::cerr |
| * don't effect how the log entry is formatted. On |
| * destruction the contents of string_, plus a newline, |
| * is inserted to the underlying stream. |
| */ |
| string_ << v; |
| |
| return *this; |
| } |
| |
| /* Handle stream manipulators. */ |
| typedef ::std::ostream& (StdManip1)(::std::ostream &os); |
| typedef ::std::ios_base& (StdManip2)(::std::ios_base &os); |
| GtestsUtil_Log& operator<<(StdManip1 m); |
| GtestsUtil_Log& operator<<(StdManip2 m); |
| |
| private: |
| GtestsUtil_Log(); |
| std::ostringstream string_; |
| std::ostream& stream_; |
| const enum LogSeverity severity_; |
| }; |
| |
| /* Log Macro |
| * |
| * Caller is expected to use one of: |
| * |
| * LOG(INFO) |
| * LOG(WARNING) |
| * LOG(ERROR) |
| * LOG(FATAL) |
| * |
| * All four of the above forms of the LOG macro cause a prefix of |
| * the following format: |
| * |
| * SMMDD hh:mm:ss.uuuuuu ttttttt ffffff:llll] |
| * |
| * where: |
| * |
| * S - severity - one of I (info), W (warning), E (error), or F (fatal) |
| * MM - month - 01 (January) to (12) December |
| * DD - day of month |
| * hh - hour |
| * mm - minute |
| * ss - seconds |
| * uuuuuu - micro-seconds |
| * ttttttt - thread ID |
| * ffffff - filename |
| * llll - line number |
| * |
| * the MM, DD, hh, mm, ss, and uuuuuu fields above are prefixed with |
| * zeros as needed to be of the length shown above. While the thread |
| * ID is prefixed with space characters as needed to be a total of 7 |
| * characters long. The filename and line numbers are displayed in |
| * whatever minimal number of characters needed to display their entire |
| * value. The INFO and WARNING forms of the LOG macros send their |
| * output to std::cout, while the ERROR and FATAL forms send it to |
| * std::stderr. |
| * |
| * Although not derived from any of the standard stream classes, the |
| * underlying GtestsUtil_Log class overloads the << operator so that |
| * ostream objects and stream manipulators can be used to the temporary |
| * object created by the various forms of the LOG macro. For example, |
| * the following will display to std::cout the hex value of a variable |
| * named foo: |
| * |
| * LOG(INFO) << "foo: 0x" << std::hex << foo; |
| * |
| * After displaying the log message prefix and anything pushed via the |
| * << operator, a newline is displayed and the stream is flushed. |
| * Additionally, the FATAL form of the LOG macro causes a TEST_ASSERT failure. |
| */ |
| #define LOG(severity) \ |
| GtestsUtil_Log(__FILE__, __LINE__, GtestsUtil_Log::severity) |
| |
| /* CHECK Macros |
| * |
| * A minimal implementation of the CHECK macros, from google3. As with |
| * the LOG macro, in the future these macros and underlying classes may |
| * be enhanced, but in general tests that need more than this minimal |
| * implementation should be implemented and maintained within google3. |
| * |
| * The basic form of the CHECK macro takes a single boolean expression. |
| * Under normal conditions this expression should evaluate to true. When |
| * true, the CHECK macro effectively becomes a null-operation. When |
| * true, expressions on the right-hand-side of a << operator are not |
| * even evaluated. In contrast, when the expression is false, a LOG(FATAL) |
| * is used to display a log prefix and the values pushed to the CHECK |
| * macro, via the << operator. Further, the use of LOG(FATAL) causes |
| * a TEST_ASSERT failure, after the values are displayed. |
| * |
| * There are additional forms of the CHECK macro that instead of taking |
| * a Boolean expression, take two values. Those two values are compared |
| * via an operation specified by a suffix to the CHECK macro name. The |
| * supported forms of these macros and the operation performed are: |
| * |
| * CHECK_EQ == (Equal) |
| * CHECK_NE != (Not Equal) |
| * CHECK_LE <= (Less Than or Equal) |
| * CHECK_LT < (Less Than) |
| * CHECK_GE >= (Greater Than or Equal) |
| * CHECK_GT > (Greater Than) |
| * |
| * Note: The CHECK macro intentionally uses a while() with |
| * no braces. This effectively forms what appears |
| * to be a short-circuit evaluation of the << operator. |
| * For example, caller might use this macro as: |
| * |
| * CHECK(cond) << "n: " << n++; |
| * |
| * Because no braces were used, the caller can |
| * add << operators to the right of the macro |
| * expansion. While the use of while causes the |
| * << operands to only be evaluated when the condition |
| * is false. In the above example, n is only increamented |
| * when cond is false. |
| */ |
| #define CHECK(condition) \ |
| while (!(condition)) \ |
| LOG(FATAL) << "FAILED: " #condition << std::endl |
| |
| #define CHECK_EQ(val1, val2) GTESTSUTIL_CHECK_OP(==, val1, val2) |
| #define CHECK_NE(val1, val2) GTESTSUTIL_CHECK_OP(!=, val1, val2) |
| #define CHECK_LE(val1, val2) GTESTSUTIL_CHECK_OP(<=, val1, val2) |
| #define CHECK_LT(val1, val2) GTESTSUTIL_CHECK_OP(< , val1, val2) |
| #define CHECK_GE(val1, val2) GTESTSUTIL_CHECK_OP(>=, val1, val2) |
| #define CHECK_GT(val1, val2) GTESTSUTIL_CHECK_OP(> , val1, val2) |
| #define GTESTSUTIL_CHECK_OP(condition, val1, val2) \ |
| /* Note: Intentional use of while() with no braces. \ |
| * See description of CHECK macro above for \ |
| * explanation. \ |
| */ \ |
| while (!(val1 condition val2)) \ |
| LOG(FATAL) << "FAILED: " << #val1 << ' ' << #condition << ' ' \ |
| << #val2 << std::endl \ |
| << "val1: " << val1 << std::endl \ |
| << "val2: " << val2 << std::endl \ |
| |
| /* Metrics - C++ Language Interface |
| * |
| * Note: C-language portion of interface described above, within "extern C" |
| * portion of this header. See above, metric_post_. |
| */ |
| class GtestsUtilMetrics { |
| public: |
| /* Post a set of metrics. |
| * |
| * name: ^[a-zA-Z_]+[0-9a-zA-Z_]*$ |
| * values: vector of type uint64_t, int64_t, float, or double. |
| * units: ^[a-zA-Z_%]+[0-9.a-zA-Z_/%^]*$ |
| * Characters of /, ^, and % provided to support units |
| * like "meters/second^2" and "%_of_baseline". |
| */ |
| static const std::string kMetricsNameRe; |
| static const std::string kMetricsUnitsRe; |
| |
| template <typename T> |
| static void Post(const std::string& name, const std::vector<T>& values, |
| const std::string& units) { |
| Post(name, values.cbegin(), values.cend(), units); |
| } |
| template <typename T> |
| static void Post(const std::string& name, |
| const T begin, const T end, const std::string& units); |
| |
| private: |
| static void Initialize(); |
| }; |
| |
| #endif /* __cplusplus */ |
| #endif /* _GTESTS_TEST_UTIL_H */ |