Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add linker wrap for mocking #957

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 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_SYSTEM_NAME} MATCHES "Linux")
set(HAVE_WRAP TRUE)
list(APPEND RE_DEFINITIONS HAVE_WRAP)
endif()

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

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

if(USE_OPENSSL)
list(APPEND SRCS
tls.c
Expand Down Expand Up @@ -175,6 +190,15 @@ 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
-Wl,--wrap=epoll_ctl
-Wl,--wrap=getaddrinfo
-Wl,--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;
}
Loading