Commit e5432341 authored by Marek Vavruša's avatar Marek Vavruša

tests: basic unittests for cache and context with cmocka

parent 202e1623
......@@ -26,9 +26,11 @@ lib/resolve.c
lib/resolve.h
lib/rplan.c
lib/rplan.h
lib/utils.h
lib/zonecut.c
lib/zonecut.h
tests/Makefile.am
tests/test.h
tests/test_cache.c
tests/test_context.c
tests/test_resolve.c
lib/utils.h
......@@ -7,6 +7,7 @@ LDADD = \
$(cmocka_LIBS)
check_PROGRAMS = \
test_cache \
test_context \
test_resolve
......
/* 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/>.
*/
#pragma once
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <ftw.h>
#include <unistd.h>
#include <cmocka.h>
#include <libknot/internal/mempattern.h>
#include <libknot/descriptor.h>
#include <libknot/rrset.h>
#include <libknot/errcode.h>
/*! \brief Memory context using CMocka allocator. */
static inline void test_mm_ctx_init(mm_ctx_t *mm)
{
mm_ctx_init(mm);
}
static inline int _remove_file(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
{
return remove(fpath);
}
/*! \brief Recursively delete directory. */
static inline int test_tmpdir_remove(const char *path)
{
return nftw(path, _remove_file, 64, FTW_DEPTH | FTW_PHYS);
}
/*! \brief Create temporary directory. */
static inline const char* test_tmpdir_create(void)
{
static char env_path[64] = "./tmpXXXXXX";
return mkdtemp(env_path);
}
/*! \brief Generate random string with given length. */
static inline void test_randstr(char* dst, size_t len)
{
if (len == 0) {
return;
}
for (int i = 0; i < len - 1; ++i) {
dst[i] = '0' + (int) (('Z'-'0') * (rand() / (RAND_MAX + 1.0)));
}
dst[len - 1] = '\0';
return;
}
/*! \brief Init RRSet with type TXT, random owner and random payload.
* \note Static memory reused, copy it if you need persistence.
*/
static inline void test_random_rr(knot_rrset_t *rr, uint32_t ttl)
{
static uint8_t owner_buf[KNOT_DNAME_MAXLEN];
static uint8_t rdata_buf[65535];
uint16_t num = rand() % (sizeof(owner_buf) - 2);
uint8_t tmp_buf[KNOT_DNAME_MAXLEN];
/* Create random label. */
owner_buf[0] = num;
test_randstr((char *)(owner_buf + 1), owner_buf[0] + 1);
/* Create payload */
tmp_buf[0] = num;
test_randstr((char *)(tmp_buf + 1), tmp_buf[0] + 1);
knot_rdata_init(rdata_buf, num + 1, tmp_buf, ttl);
/* Assign static buffers. */
knot_rrset_init(rr, owner_buf, KNOT_RRTYPE_TXT, KNOT_CLASS_IN);
rr->rrs.rr_count = 1;
rr->rrs.data = rdata_buf;
}
/* 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 "tests/test.h"
#include <libknot/internal/mempool.h>
#include "lib/cache.h"
mm_ctx_t global_mm;
namedb_txn_t global_txn;
knot_rrset_t global_rr;
const char *global_env;
#define CACHE_SIZE 100*1024
#define CACHE_TTL 1
/* Test cache open */
static void test_open(void **state)
{
printf("OPENSDFDSFSDFSFSDFSDF\n");
*state = kr_cache_open(global_env, &global_mm, CACHE_SIZE);
assert_non_null(*state);
}
/* Test cache teardown. */
static void test_close(void **state)
{
kr_cache_close(*state);
*state = NULL;
}
/* Open transaction */
static namedb_txn_t *test_txn_write(void **state)
{
assert_non_null(*state);
assert_int_equal(kr_cache_txn_begin(*state, &global_txn, 0), KNOT_EOK);
return &global_txn;
}
/* Open transaction */
static namedb_txn_t *test_txn_rdonly(void **state)
{
assert_non_null(*state);
assert_int_equal(kr_cache_txn_begin(*state, &global_txn, NAMEDB_RDONLY), KNOT_EOK);
return &global_txn;
}
/* Test cache write */
static void test_insert(void **state)
{
test_random_rr(&global_rr, CACHE_TTL);
namedb_txn_t *txn = test_txn_write(state);
int ret = kr_cache_insert(txn, &global_rr, 0);
if (ret == KNOT_EOK) {
ret = kr_cache_txn_commit(txn);
} else {
kr_cache_txn_abort(txn);
}
assert_int_equal(ret, KNOT_EOK);
}
/* Test cache read */
static void test_query(void **state)
{
uint32_t timestamp = 0;
knot_rrset_t cache_rr;
knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
namedb_txn_t *txn = test_txn_rdonly(state);
int query_ret = kr_cache_query(txn, &cache_rr, &timestamp);
bool rr_equal = knot_rrset_equal(&global_rr, &cache_rr, KNOT_RRSET_COMPARE_WHOLE);
kr_cache_txn_abort(txn);
assert_int_equal(query_ret, KNOT_EOK);
assert_true(rr_equal);
}
/* Test cache read (simulate aged entry) */
static void test_query_aged(void **state)
{
uint32_t timestamp = CACHE_TTL;
knot_rrset_t cache_rr;
knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
namedb_txn_t *txn = test_txn_rdonly(state);
int ret = kr_cache_query(txn, &cache_rr, &timestamp);
assert_int_equal(ret, KNOT_ENOENT);
}
/* Test cache fill */
static void test_fill(void **state)
{
namedb_txn_t *txn = test_txn_write(state);
/* Fill with random values. */
int ret = KNOT_EOK;
for (unsigned i = 0; i < CACHE_SIZE; ++i) {
knot_rrset_t rr;
test_random_rr(&rr, CACHE_TTL);
ret = kr_cache_insert(txn, &rr, 0);
if (ret != KNOT_EOK) {
break;
}
/* Intermediate commit */
if (i % 10 == 0) {
ret = kr_cache_txn_commit(txn);
if (ret != KNOT_EOK) {
txn = NULL;
break;
}
txn = test_txn_write(state);
}
}
/* Size reached, commit may fail. */
(void) kr_cache_txn_commit(txn);
/* Expect we run out of space */
assert_int_equal(ret, KNOT_ESPACE);
}
/* Test cache clear */
static void test_clear(void **state)
{
namedb_txn_t *txn = test_txn_write(state);
int preempt_ret = kr_cache_clear(txn);
int commit_ret = kr_cache_txn_commit(txn);
assert_int_equal(preempt_ret, KNOT_EOK);
assert_int_equal(commit_ret, KNOT_EOK);
}
int main(void)
{
/* Initialize */
test_mm_ctx_init(&global_mm);
global_env = test_tmpdir_create();
const UnitTest tests[] = {
/* Cache persistence */
group_test_setup(test_open),
unit_test(test_insert),
unit_test(test_query),
/* Cache aging */
unit_test(test_query_aged),
/* Cache fill */
unit_test(test_fill),
unit_test(test_clear),
group_test_teardown(test_close)
};
int ret = run_group_tests(tests);
/* Cleanup */
test_tmpdir_remove(global_env);
return ret;
}
......@@ -14,28 +14,34 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include "tests/test.h"
#include <libknot/mempattern.h>
#include "lib/context.h"
/* \note Create context and close it. */
static void tests_ctx_create(void **state)
mm_ctx_t global_mm;
static struct kr_context global_context;
/* Create resolution context */
static void text_context_init(void **state)
{
mm_ctx_t mm;
mm_ctx_init(&mm);
struct kr_context ctx;
assert_int_equal(kr_context_init(&ctx, &mm), 0);
assert_int_equal(kr_context_deinit(&ctx), 0);
int ret = kr_context_init(&global_context, &global_mm);
assert_int_equal(ret, KNOT_EOK);
*state = &global_context;
}
/* Delete it */
static void text_context_deinit(void **state)
{
int ret = kr_context_deinit(*state);
assert_int_equal(ret, KNOT_EOK);
}
int main(void)
{
test_mm_ctx_init(&global_mm);
const UnitTest tests[] = {
unit_test(tests_ctx_create),
unit_test_teardown(text_context_init, text_context_deinit),
};
return run_tests(tests);
......
......@@ -14,29 +14,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include "tests/test.h"
#include <libknot/mempattern.h>
#include <libknot/descriptor.h>
#include "lib/resolve.h"
/* \note Synchronous resolution. */
void test_resolve_sync(void **state)
{
struct kr_context ctx;
kr_context_init(&ctx, NULL);
struct kr_result res;
const knot_dname_t *qname = (const uint8_t *)"\x06""dnssec""\x02""cz";
int ret = kr_resolve(&ctx, &res, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A);
assert_int_equal(ret, 0);
kr_result_deinit(&res);
qname = (const uint8_t *)"\x04""mail""\x07""vavrusa""\x03""com";
ret = kr_resolve(&ctx, &res, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A);
assert_int_equal(ret, 0);
kr_context_deinit(&ctx);
/* \todo CMocka should provide responses here. */
}
int main(void)
......
Markdown is supported
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