test_integration.c 4.28 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*  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 "tests/test.h"
20
#include "lib/rplan.h"
21 22 23 24 25
#include "lib/resolve.h"

/*
 * Globals
 */
26 27 28
static mm_ctx_t global_mm;               /* Test memory context */
static struct kr_context global_context; /* Resolution context */
static const char *global_tmpdir = NULL; /* Temporary directory */
29 30 31 32 33 34

/*
 * Test driver global variables.
 */
extern struct timeval g_mock_time;        /* Mocked system time */
extern PyObject *g_mock_server;           /* Mocked endpoint for recursive queries */
35 36 37 38 39 40 41

/*
 * PyModule implementation.
 */

static PyObject* init(PyObject* self, PyObject* args)
{
42 43 44 45 46
	const char *config= NULL;
	if (!PyArg_ParseTuple(args, "s", &config)) {
		return NULL;
	}

47
	/* Initialize mock variables */
48 49
	memset(&g_mock_time, 0, sizeof(struct timeval));
	g_mock_server = NULL;
50 51

	/* Initialize resolution context */
52 53 54 55
	#define CACHE_SIZE 100*1024
	test_mm_ctx_init(&global_mm);
	kr_context_init(&global_context, &global_mm);
	global_tmpdir = test_tmpdir_create();
56
	assert(global_tmpdir);
57
	global_context.cache = kr_cache_open(global_tmpdir, &global_mm, CACHE_SIZE);
58
	assert(global_context.cache);
59

60
	/* Test context options. */
61 62 63 64 65 66
	global_context.options = QUERY_TCP;

	/* No configuration parsing support yet. */
	if (strstr(config, "query-minimization: on") == NULL) {
		global_context.options |= QUERY_NO_MINIMIZE; 
	}
67

Marek Vavruša's avatar
Marek Vavruša committed
68
	return Py_BuildValue("");
69 70 71 72 73 74 75 76 77 78 79
}

static PyObject* deinit(PyObject* self, PyObject* args)
{
	if (global_tmpdir == NULL) {
		return NULL;
	}

	kr_context_deinit(&global_context);
	test_tmpdir_remove(global_tmpdir);
	global_tmpdir = NULL;
80 81 82
	if (g_mock_server) {
		Py_XDECREF(g_mock_server);
		g_mock_server = NULL;
83
	}
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

	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)) {
		return NULL;
	}

	/* 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) {
		knot_pkt_free(&query);
		return NULL;
	}

	/* 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;
	}

126 127
	g_mock_time.tv_sec  = arg_time;
	g_mock_time.tv_usec = 0;
128 129 130 131

	return Py_BuildValue("");
}

132
static PyObject* set_server(PyObject *self, PyObject *args)
133
{
134 135 136
	/* Get client socket getter method. */
	PyObject *arg_client = NULL;
	if (!PyArg_ParseTuple(args, "O", &arg_client)) {
137 138 139
		return NULL;
	}

140 141
	/* Swap the server implementation. */
	Py_XINCREF(arg_client);
142 143
	Py_XDECREF(g_mock_server);
	g_mock_server = arg_client;
144 145 146 147 148 149 150 151 152

	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."},
153
    {"set_server", set_server, METH_VARARGS, "Set fake server object."},
154 155 156 157 158 159 160
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC init_test_integration(void)
{
	(void) Py_InitModule("_test_integration", module_methods);
}