Skip to content
Snippets Groups Projects
Commit fe1b3bd7 authored by Marek Vavruša's avatar Marek Vavruša
Browse files

test: cleanup of old files

parent ead03815
Branches
Tags
No related merge requests found
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include <dlfcn.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <fcntl.h>
#include <libknot/descriptor.h>
#include <libknot/packet/pkt.h>
#include <libknot/internal/net.h>
#include <Python.h>
/*
* Globals
*/
#ifdef __APPLE__
#define MOCK__TZ_ARG void
#define MOCK__SOCKADDR_ARG struct sockaddr *restrict
#define MOCK__CONST_SOCKADDR_ARG const struct sockaddr *
#define MOCK__GET_SOCKADDR(arg) arg
#define errno_location __error()
#else
#define MOCK__TZ_ARG struct timezone
#define MOCK__SOCKADDR_ARG __SOCKADDR_ARG
#define MOCK__CONST_SOCKADDR_ARG __CONST_SOCKADDR_ARG
#define MOCK__GET_SOCKADDR(arg) arg.__sockaddr__
#define errno_location __errno_location()
#endif
struct timeval g_mock_time; /* Mocked system time */
PyObject *g_mock_server = NULL; /* Mocked endpoint for recursive queries */
struct sockaddr_storage original_dst = { 0 };
int original_dst_len = 0;
int connected_fd = -1;
int (*original_connect)(int __fd, MOCK__CONST_SOCKADDR_ARG __addr,
socklen_t __len) = NULL;
ssize_t (*original_recvfrom) (int __fd, void *__restrict __buf, size_t __n,
int __flags, MOCK__SOCKADDR_ARG __addr,
socklen_t *__restrict __addr_len) = NULL;
ssize_t (*original_recv) (int __fd, void *__buf,
size_t __n, int __flags) = NULL;
int (*original_select) (int __nfds, fd_set *__restrict __readfds,
fd_set *__restrict __writefds,
fd_set *__restrict __exceptfds,
struct timeval *__restrict __timeout) = NULL;
#define FIND_ORIGINAL(fname) \
if (original_##fname == NULL) \
{ \
original_##fname = dlsym(RTLD_NEXT,#fname); \
assert(original_##fname); \
}
int gettimeofday(struct timeval *tv, MOCK__TZ_ARG *tz)
{
memcpy(tv, &g_mock_time, sizeof(struct timeval));
return 0;
}
ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n,
int __flags, MOCK__SOCKADDR_ARG __addr,
socklen_t *__restrict __addr_len)
{
ssize_t ret = -1;
struct sockaddr *addr = MOCK__GET_SOCKADDR(__addr);
FIND_ORIGINAL(recvfrom);
if (__fd == connected_fd) {
/* May block, must unlock GIL */
if ((__flags & MSG_DONTWAIT) == 0) {
Py_BEGIN_ALLOW_THREADS
ret = original_recvfrom( __fd,__buf,__n,__flags,__addr,__addr_len);
Py_END_ALLOW_THREADS
} else {
ret = original_recvfrom( __fd,__buf,__n,__flags,__addr,__addr_len);
}
if (addr != NULL && *__addr_len > 0) {
int len = original_dst_len;
if (len < *__addr_len)
len = *__addr_len;
memcpy(addr, &original_dst, len);
}
} else {
ret = original_recvfrom( __fd,__buf,__n,__flags,__addr,__addr_len);
}
return ret;
}
ssize_t recv (int __fd, void *__buf, size_t __n, int __flags)
{
ssize_t ret;
FIND_ORIGINAL(recv);
if (__fd == connected_fd) {
/* May block, must unlock GIL */
if ((__flags & MSG_DONTWAIT) == 0) {
Py_BEGIN_ALLOW_THREADS
ret = original_recv (__fd,__buf,__n,__flags);
Py_END_ALLOW_THREADS
} else{
ret = original_recv (__fd,__buf,__n,__flags);
}
} else {
ret = original_recv (__fd,__buf,__n,__flags);
}
return ret;
}
int select (int __nfds, fd_set *__restrict __readfds,
fd_set *__restrict __writefds,
fd_set *__restrict __exceptfds,
struct timeval *__restrict __timeout)
{
int ret;
FIND_ORIGINAL(select);
if (connected_fd != -1 && __nfds > connected_fd && (
(__readfds != NULL && FD_ISSET(connected_fd, __readfds)) ||
(__writefds != NULL && FD_ISSET(connected_fd, __writefds)) ||
(__exceptfds != NULL && FD_ISSET(connected_fd, __exceptfds))
)) {
struct timeval _timeout = {0, 200 * 1000};
Py_BEGIN_ALLOW_THREADS
ret = original_select (__nfds,
__readfds,__writefds,__exceptfds,&_timeout);
Py_END_ALLOW_THREADS
} else {
ret = original_select (__nfds,
__readfds,__writefds,__exceptfds,__timeout);
}
return ret;
}
int connect(int __fd, MOCK__CONST_SOCKADDR_ARG __addr, socklen_t __len)
{
Dl_info dli = {0};
char *python_addr = NULL;
struct addrinfo hints;
struct addrinfo *info = NULL;
int ret, parse_ret, python_port = 0, flowinfo, scopeid, local_socktype;
socklen_t local_socktypelen = sizeof(int);
const struct sockaddr *dst_addr = MOCK__GET_SOCKADDR(__addr);
char right_caller[] = "net_connected_socket";
PyObject *result = NULL;
char addr_str[SOCKADDR_STRLEN];
char pport[32];
/* @note This is only going to work if we're calling from a function which has a
symbol in the symbol table, must link dynamically. */
FIND_ORIGINAL(connect);
dladdr (__builtin_return_address (0), &dli);
if (!dli.dli_sname ||
(strncmp(right_caller,dli.dli_sname,strlen(right_caller)) != 0))
return original_connect (__fd, __addr, __len);
sockaddr_tostr(addr_str, SOCKADDR_STRLEN,
(const struct sockaddr_storage *)dst_addr);
if (dst_addr->sa_family != AF_INET && dst_addr->sa_family != AF_INET6) {
errno = EINVAL;
return -1;
}
getsockopt(__fd, SOL_SOCKET, SO_TYPE,
&local_socktype, &local_socktypelen);
if (local_socktype == SOCK_DGRAM) {
result = PyObject_CallMethod(g_mock_server, "get_server_socket",
"si", addr_str, dst_addr->sa_family);
if (result == NULL) {
errno = ECONNABORTED;
return -1;
}
} else {
errno = EINVAL;
return -1;
}
if (dst_addr->sa_family == AF_INET) {
parse_ret = PyArg_ParseTuple(result, "si",
&python_addr, &python_port);
} else {
parse_ret = PyArg_ParseTuple(result, "siii",
&python_addr, &python_port, &flowinfo, &scopeid);
}
Py_DECREF(result);
if (!parse_ret) {
errno = ECONNABORTED;
return -1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = dst_addr->sa_family;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = IPPROTO_UDP;
sprintf (pport,"%i",python_port);
ret = getaddrinfo(python_addr,pport,&hints,&info);
if (ret) {
errno = ECONNABORTED;
return -1;
}
connected_fd = __fd;
ret = original_connect (__fd, info->ai_addr, info->ai_addrlen);
freeaddrinfo(info);
memcpy(&original_dst,dst_addr,__len);
original_dst_len = __len;
return ret;
}
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Python.h>
#include <libknot/internal/namedb/namedb_lmdb.h>
#include "tests/test.h"
#include "lib/rplan.h"
#include "lib/resolve.h"
/*
* Globals
*/
static mm_ctx_t global_mm; /* Test memory context */
static module_array_t global_modules; /* Array of modules. */
static struct kr_context global_context; /* Resolution context */
static const char *global_tmpdir = NULL; /* Temporary directory */
/*
* Test driver global variables.
*/
extern struct timeval g_mock_time; /* Mocked system time */
extern PyObject *g_mock_server; /* Mocked endpoint for recursive queries */
/*
* PyModule implementation.
*/
static PyObject* init(PyObject* self, PyObject* args)
{
const char *config= NULL;
if (!PyArg_ParseTuple(args, "s", &config)) {
return NULL;
}
/* Initialize mock variables */
memset(&g_mock_time, 0, sizeof(struct timeval));
g_mock_server = NULL;
/* Load basic modules. */
array_init(global_modules);
const char *load_modules[3] = {"iterate", "rrcache", "pktcache"};
for (unsigned i = 0; i < 3; ++i) {
struct kr_module *mod = malloc(sizeof(*mod));
kr_module_load(mod, load_modules[i], NULL);
array_push(global_modules, mod);
}
/* Initialize resolution context */
mm_ctx_init(&global_mm);
memset(&global_context, 0, sizeof(struct kr_context));
global_context.pool = &global_mm;
global_context.modules = &global_modules;
/* Create cache */
global_tmpdir = test_tmpdir_create();
assert(global_tmpdir);
struct namedb_lmdb_opts opts;
memset(&opts, 0, sizeof(opts));
opts.path = global_tmpdir;
opts.mapsize = 100 * 4096;
int ret = kr_cache_open(&global_context.cache, NULL, &opts, &global_mm);
if (ret != 0) {
return NULL;
}
/* Create RTT + reputation tracking */
global_context.cache_rtt = malloc(lru_size(kr_nsrep_lru_t, 1024));
assert(global_context.cache_rtt);
lru_init(global_context.cache_rtt, 1024);
global_context.cache_rep = malloc(lru_size(kr_nsrep_lru_t, 512));
assert(global_context.cache_rep);
lru_init(global_context.cache_rep, 512);
global_context.options = QUERY_NO_THROTTLE;
/* No configuration parsing support yet. */
if (strstr(config, "query-minimization: on") == NULL) {
global_context.options |= QUERY_NO_MINIMIZE;
}
return Py_BuildValue("");
}
static PyObject* deinit(PyObject* self, PyObject* args)
{
if (global_tmpdir == NULL) {
return NULL;
}
for (size_t i = 0; i < global_modules.len; ++i) {
kr_module_unload(global_modules.at[i]);
}
array_clear(global_modules);
kr_cache_close(&global_context.cache);
lru_deinit(global_context.cache_rtt);
lru_deinit(global_context.cache_rep);
free(global_context.cache_rtt);
free(global_context.cache_rep);
test_tmpdir_remove(global_tmpdir);
global_tmpdir = NULL;
if (g_mock_server) {
Py_XDECREF(g_mock_server);
g_mock_server = NULL;
}
return Py_BuildValue("");
}
static PyObject* resolve(PyObject *self, PyObject *args)
{
const char *query_wire = NULL;
size_t query_size = 0;
if (!PyArg_ParseTuple(args, "s#", &query_wire, &query_size)) {
PyObject *out = Py_BuildValue("s#", NULL, 0);
return out;
}
/* Prepare input */
knot_pkt_t *query = knot_pkt_new((uint8_t *)query_wire, query_size, &global_mm);
assert(query);
int ret = knot_pkt_parse(query, 0);
if (ret != KNOT_EOK) {
PyObject *out = Py_BuildValue("s#", NULL, 0);
knot_pkt_free(&query);
return out;
}
/* Resolve query */
knot_pkt_t *answer = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, &global_mm);
assert(answer);
knot_pkt_init_response(answer, query);
ret = kr_resolve(&global_context, answer, knot_pkt_qname(query),
knot_pkt_qclass(query), knot_pkt_qtype(query));
/* Return wire and cleanup. */
PyObject *out = Py_BuildValue("s#", answer->wire, answer->size);
knot_pkt_free(&answer);
knot_pkt_free(&query);
return out;
}
static PyObject* set_time(PyObject *self, PyObject *args)
{
unsigned long arg_time = 0;
if (!PyArg_ParseTuple(args, "k", &arg_time)) {
return NULL;
}
g_mock_time.tv_sec += arg_time;
g_mock_time.tv_usec = 0;
return Py_BuildValue("");
}
static PyObject* set_server(PyObject *self, PyObject *args)
{
/* Get client socket getter method. */
PyObject *arg_client = NULL;
if (!PyArg_ParseTuple(args, "O", &arg_client)) {
return NULL;
}
/* Swap the server implementation. */
Py_XINCREF(arg_client);
Py_XDECREF(g_mock_server);
g_mock_server = arg_client;
return Py_BuildValue("");
}
static PyMethodDef module_methods[] = {
{"init", init, METH_VARARGS, "Initialize resolution context."},
{"deinit", deinit, METH_VARARGS, "Clean up resolution context."},
{"resolve", resolve, METH_VARARGS, "Resolve query."},
{"set_time", set_time, METH_VARARGS, "Set mock system time."},
{"set_server", set_server, METH_VARARGS, "Set fake server object."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC init_test_integration(void)
{
(void) Py_InitModule("_test_integration", module_methods);
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment