#ifndef test_utils_h
#define test_utils_h
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include "../copyfile.h"
#define BSIZE_B 128
#define MAX_DISK_IMAGE_SIZE_MB 1024
#define DEFAULT_NAME_MOD 999
#define DEFAULT_OPEN_FLAGS O_CREAT|O_TRUNC|O_RDWR
#define DEFAULT_OPEN_PERM 0666
#define DEFAULT_MKDIR_PERM 0777
#define DISK_IMAGE_PATH "/tmp/copyfile_sparse.sparseimage"
#define VOLUME_NAME "apfs_sparse"
#define DEFAULT_FSTYPE "JHFS+"
#define APFS_FSTYPE "apfs"
#define MOUNT_PATH "/Volumes/" VOLUME_NAME
#define HDIUTIL_PATH "/usr/bin/hdiutil"
#define DIFF_PATH "/usr/bin/diff"
bool verify_st_flags(struct stat *sb, uint32_t flags_to_expect);
bool verify_fd_contents(int orig_fd, off_t orig_pos, int copy_fd, off_t copy_pos, size_t length);
bool verify_copy_contents(const char *orig_name, const char *copy_name);
bool verify_copy_sizes(struct stat *orig_sb, struct stat *copy_sb, copyfile_state_t cpf_state,
bool do_sparse, off_t src_start);
int create_hole_in_fd(int fd, off_t offset, off_t length);
void create_test_file_name(const char *dir, const char *postfix, int id, char *string_out);
void disk_image_create(const char *fstype, size_t size_in_mb);
void disk_image_destroy(bool allow_failure);
static inline void
__attribute__((format (printf, 3, 4)))
__attribute__((noreturn))
assert_fail_(const char *file, int line, const char *assertion, ...)
{
va_list args;
va_start(args, assertion);
char *msg;
vasprintf(&msg, assertion, args);
va_end(args);
printf("\n%s:%u: error: %s\n", file, line, msg);
exit(1);
}
#define assert_fail(str, ...) \
assert_fail_(__FILE__, __LINE__, str, ## __VA_ARGS__)
#undef assert
#define assert(condition) \
do { \
if (!(condition)) \
assert_fail_(__FILE__, __LINE__, \
"assertion failed: %s", #condition); \
} while (0)
#define assert_with_errno_(condition, condition_str) \
do { \
if (!(condition)) \
assert_fail_(__FILE__, __LINE__, "%s failed: %s", \
condition_str, strerror(errno)); \
} while (0)
#define assert_with_errno(condition) \
assert_with_errno_((condition), #condition)
#define assert_no_err(condition) \
assert_with_errno_(!(condition), #condition)
#define assert_equal(lhs, rhs, fmt) \
do { \
typeof (lhs) lhs_ = (lhs); \
typeof (lhs) rhs_ = (rhs); \
if (lhs_ != rhs_) \
assert_fail(#lhs " (" fmt ") != " #rhs " (" fmt ")", \
lhs_, rhs_); \
} while (0)
#define assert_equal_(lhs, rhs, lhs_str, rhs_str, fmt) \
do { \
typeof (lhs) lhs_ = (lhs); \
typeof (lhs) rhs_ = (rhs); \
if (lhs_ != rhs_) \
assert_fail(lhs_str " (" fmt ") != " rhs_str " (" fmt ")", \
lhs_, rhs_); \
} while (0)
#define assert_equal_int(lhs, rhs) assert_equal_(lhs, rhs, #lhs, #rhs, "%d")
#define assert_equal_ll(lhs, rhs) assert_equal_(lhs, rhs, #lhs, #rhs, "%lld")
#define assert_equal_str(lhs, rhs) \
do { \
const char *lhs_ = (lhs), *rhs_ = (rhs); \
if (strcmp(lhs_, rhs_)) \
assert_fail("\"%s\" != \"%s\"", lhs_, rhs_); \
} while (0)
#define ignore_eintr(x, error_val) \
({ \
typeof(x) eintr_ret_; \
do { \
eintr_ret_ = (x); \
} while (eintr_ret_ == (error_val) && errno == EINTR); \
eintr_ret_; \
})
#endif