Skip to content

Commit

Permalink
test: add linker wrap for mocking
Browse files Browse the repository at this point in the history
  • Loading branch information
sreimers committed Sep 13, 2023
1 parent 0d6205e commit f4b70b5
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 0 deletions.
23 changes: 23 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ include_directories(

find_package(re CONFIG REQUIRED HINTS ../cmake)

if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "GNU")
set(HAVE_WRAP TRUE)
list(APPEND RE_DEFINITIONS HAVE_WRAP)
endif()

##############################################################################
#
# Source/Header section
Expand Down Expand Up @@ -143,6 +148,14 @@ set(SRCS
websock.c
)

if(HAVE_WRAP)
list(APPEND SRCS
wrap/wrap.c
wrap/epoll.c
wrap/getaddrinfo.c
)
endif()

if(USE_OPENSSL)
list(APPEND SRCS
tls.c
Expand Down Expand Up @@ -175,6 +188,16 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS 1)
target_link_libraries(${PROJECT_NAME} PRIVATE ${LINKLIBS})
target_compile_definitions(${PROJECT_NAME} PRIVATE ${RE_DEFINITIONS})

if(HAVE_WRAP)
target_link_options(${PROJECT_NAME} PRIVATE
-Wl,
--wrap=epoll_create,
--wrap=epoll_ctl,
--wrap=getaddrinfo,
--wrap=freeaddrinfo
)
endif()

if(USE_OPENSSL)
target_include_directories(${PROJECT_NAME} PRIVATE ${OPENSSL_INCLUDE_DIR})
endif()
9 changes: 9 additions & 0 deletions test/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,3 +547,12 @@ int dns_server_add_srv(struct dns_server *srv, const char *name,
uint16_t pri, uint16_t weight, uint16_t port,
const char *target);
void dns_server_flush(struct dns_server *srv);


/*
* Wrap functions
*/
int wrap_will_return_int(const char *func, int ret);
int wrap_will_return_data(const char *func, void *data);
int wrap_return_int(const char *func, int *ret);
void *wrap_return_data(const char *func);
30 changes: 30 additions & 0 deletions test/wrap/epoll.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <sys/epoll.h>

#include <re.h>
#include "test.h"


int __wrap_epoll_create(int size);
int __real_epoll_create(int size);

int __wrap_epoll_create(int size)
{
int ret;

int err = wrap_return_int("epoll_create", &ret);

return err ? __real_epoll_create(size) : ret;
}


int __wrap_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int __real_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

int __wrap_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
int ret;

int err = wrap_return_int("epoll_create", &ret);

return err ? __real_epoll_ctl(epfd, op, fd, event) : ret;
}
26 changes: 26 additions & 0 deletions test/wrap/getaddrinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <netdb.h>

#include <re.h>
#include "test.h"


int __wrap_getaddrinfo(const char *restrict node, const char *restrict service,
const struct addrinfo *restrict hints,
struct addrinfo **restrict res);
int __real_getaddrinfo(const char *restrict node, const char *restrict service,
const struct addrinfo *restrict hints,
struct addrinfo **restrict res);
int __wrap_getaddrinfo(const char *restrict node, const char *restrict service,
const struct addrinfo *restrict hints,
struct addrinfo **restrict res)
{
return __real_getaddrinfo(node, service, hints, res);
}


void __wrap_freeaddrinfo(struct addrinfo *res);
void __real_freeaddrinfo(struct addrinfo *res);
void __wrap_freeaddrinfo(struct addrinfo *res)
{
__real_freeaddrinfo(res);
}
129 changes: 129 additions & 0 deletions test/wrap/wrap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include <re.h>
#include "test.h"

enum wrap_type {
WRAP_INT,
WRAP_DATA
};

struct wrap_entry {
struct le le;
char func[64];
enum wrap_type type;
union {
int ret_int;
void *ret_data;
} u;
};

static struct list wrapl = LIST_INIT;


static void entry_destruct(void *arg)
{
struct wrap_entry *e = arg;
list_unlink(&e->le);
}


static struct wrap_entry *wrap_entry_alloc(const char *func)
{
struct wrap_entry *e;

e = mem_alloc(sizeof(struct wrap_entry), entry_destruct);
if (!e)
return NULL;

str_ncpy(e->func, func, sizeof(e->func));

list_append(&wrapl, &e->le, e);

return e;
}


int wrap_will_return_int(const char *func, int ret)
{
struct wrap_entry *e;

if (!func)
return EINVAL;

e = wrap_entry_alloc(func);
if (!e)
return ENOMEM;

e->type = WRAP_INT;
e->u.ret_int = ret;

return 0;
}


int wrap_will_return_data(const char *func, void *data)
{
struct wrap_entry *e;

if (!func)
return EINVAL;

e = wrap_entry_alloc(func);
if (!e)
return ENOMEM;

e->type = WRAP_DATA;
e->u.ret_data = data;

return 0;
}


int wrap_return_int(const char *func, int *ret)
{
struct le *le;

if (!func)
return EINVAL;

LIST_FOREACH(&wrapl, le)
{
struct wrap_entry *e = le->data;

if (e->type != WRAP_INT)
continue;

if (0 == str_casecmp(e->func, func)) {
*ret = e->u.ret_int;
mem_deref(e);
return 0;
}
}

return ENODATA;
}


void *wrap_return_data(const char *func)
{
struct le *le;
void *data;

if (!func)
return NULL;

LIST_FOREACH(&wrapl, le)
{
struct wrap_entry *e = le->data;

if (e->type != WRAP_DATA)
continue;

if (0 == str_casecmp(e->func, func)) {
data = e->u.ret_data;
mem_deref(e);
return data;
}
}

return NULL;
}

0 comments on commit f4b70b5

Please sign in to comment.