diff options
Diffstat (limited to 'src/zcompile/tests')
-rw-r--r-- | src/zcompile/tests/unittests_zp_main.c | 62 | ||||
-rw-r--r-- | src/zcompile/tests/zcompile_tests.c | 425 |
2 files changed, 487 insertions, 0 deletions
diff --git a/src/zcompile/tests/unittests_zp_main.c b/src/zcompile/tests/unittests_zp_main.c new file mode 100644 index 0000000..5d8c5e9 --- /dev/null +++ b/src/zcompile/tests/unittests_zp_main.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2011 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 <config.h> +#include "knot/common.h" +#include "common/libtap/tap_unit.h" + +// Units to test +#include "zcompile_tests.c" + +// Run all loaded units +int main(int argc, char *argv[]) +{ + // Open log + //log_init(LOG_UPTO(LOG_ERR), LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING)); + + // Build test set + unit_api *tests[] = { + &zoneparser_tests_api, //! Zoneparser unit + NULL + }; + + // Plan number of tests + int id = 0; + int test_count = 0; + note("Units:"); + while (tests[id] != NULL) { + note("- %s : %d tests", tests[id]->name, + tests[id]->count(argc, argv)); + test_count += tests[id]->count(argc, argv); + ++id; + } + + plan(test_count); + + // Run tests + id = 0; + while (tests[id] != NULL) { + diag("Testing unit: %s", tests[id]->name); + tests[id]->run(argc, argv); + ++id; + } + + //log_close(); + + // Evaluate + return exit_status(); +} + diff --git a/src/zcompile/tests/zcompile_tests.c b/src/zcompile/tests/zcompile_tests.c new file mode 100644 index 0000000..5d3dce6 --- /dev/null +++ b/src/zcompile/tests/zcompile_tests.c @@ -0,0 +1,425 @@ +/* Copyright (C) 2011 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 <assert.h> + +#include "libknot/zone/zone.h" +#include "knot/zone/zone-load.h" +#include "knot/common.h" +#include "libknot/rrset.h" +#include "libknot/util/descriptor.h" +#include "zcompile/zcompile.h" + +#ifdef TEST_WITH_LDNS +#include "ldns/ldns.h" +#endif + +static int zoneparser_tests_count(int argc, char *argv[]); +static int zoneparser_tests_run(int argc, char *argv[]); + +/* + * Unit API. + */ +unit_api zoneparser_tests_api = { + "Zoneparser", + &zoneparser_tests_count, + &zoneparser_tests_run +}; + +#ifdef TEST_WITH_LDNS +/* + * Unit implementation. + */static int compare_wires_simple_zp(uint8_t *wire1, + uint8_t *wire2, uint count) +{ + int i = 0; + while (i < count && + wire1[i] == wire2[i]) { + i++; + } + return (!(count == i)); +} + +/* compares only one rdata */ +static int compare_rr_rdata_silent(knot_rdata_t *rdata, ldns_rr *rr, + uint16_t type) +{ + knot_rrtype_descriptor_t *desc = + knot_rrtype_descriptor_by_type(type); + for (int i = 0; i < rdata->count; i++) { + /* TODO check for ldns "descriptors" as well */ + if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME || + desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME || + desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME) { + assert(ldns_rr_rdf(rr, i)); + if (rdata->items[i].dname->size != + ldns_rdf_size(ldns_rr_rdf(rr, i))) { + return 1; + } + if (compare_wires_simple_zp(rdata->items[i].dname->name, + ldns_rdf_data(ldns_rr_rdf(rr, i)), + rdata->items[i].dname->size) != 0) { + return 1; + } + } else { + if (ldns_rr_rdf(rr, i) == NULL && + rdata->items[i].raw_data[0] != 0) { + return 1; + } else { + continue; + } + if (rdata->items[i].raw_data[0] != + ldns_rdf_size(ldns_rr_rdf(rr, i))) { + + /* ldns stores the size including the + * length, dnslib does not */ + if (abs(rdata->items[i].raw_data[0] - + ldns_rdf_size(ldns_rr_rdf(rr, i))) != 1) { + return 1; + } + } + if (compare_wires_simple_zp((uint8_t *) + (rdata->items[i].raw_data + 1), + ldns_rdf_data(ldns_rr_rdf(rr, i)), + rdata->items[i].raw_data[0]) != 0) { + return 1; + } + } + } + return 0; +} + +static int compare_rrset_w_ldns_rrset(const knot_rrset_t *rrset, + ldns_rr_list *rrs, + char check_rdata, char verbose) +{ + /* We should have only one rrset from ldns, although it is + * represented as rr_list ... */ + + /* TODO errors */ + + assert(rrs); + assert(rrset); + + ldns_rr_list_sort(rrs); + + /* compare headers */ + + ldns_rr *rr = ldns_rr_list_rr(rrs, 0); + + if (rrset->owner->size != ldns_rdf_size(ldns_rr_owner(rr))) { + diag("RRSet owner names differ in length"); + if (!verbose) { + return 1; + } + diag("ldns: %d, dnslib: %d", ldns_rdf_size(ldns_rr_owner(rr)), + rrset->owner->size); + diag("%s", knot_dname_to_str(rrset->owner)); + diag("%s", ldns_rdf_data(ldns_rr_owner(rr))); + return 1; + } + + if (compare_wires_simple_zp(rrset->owner->name, + ldns_rdf_data(ldns_rr_owner(rr)), + rrset->owner->size) != 0) { + diag("RRSet owner wireformats differ"); + return 1; + } + + if (rrset->type != ldns_rr_get_type(rr)) { + diag("RRset types differ"); + if (!verbose) { + return 1; + } + diag("Dnslib type: %d Ldns type: %d", rrset->type, + ldns_rr_get_type(rr)); + return 1; + } + + if (rrset->rclass != ldns_rr_get_class(rr)) { + diag("RRset classes differ"); + return 1; + } + + if (rrset->ttl != ldns_rr_ttl(rr)) { + diag("RRset TTLs differ"); + if (!verbose) { + return 1; + } + diag("dnslib: %d ldns: %d", rrset->ttl, ldns_rr_ttl(rr)); + return 1; + } + + if (!check_rdata) { + return 0; + } + + /* compare rdatas */ + + /* sort dnslib rdata */ + + knot_rdata_t *tmp_rdata = rrset->rdata; + + rr = ldns_rr_list_pop_rr(rrs); + + char found; + + while (rr != NULL) { + found = 0; + tmp_rdata = rrset->rdata; + while (!found && + tmp_rdata->next != rrset->rdata) { + if (compare_rr_rdata_silent(tmp_rdata, rr, + rrset->type) == 0) { + found = 1; + } + tmp_rdata = tmp_rdata->next; + } + + if (!found && + compare_rr_rdata_silent(tmp_rdata, rr, rrset->type) == 0) { + found = 1; + } + + /* remove the found rdata from list */ + if (!found) { + diag("RRsets rdata differ"); + return 1; + } + ldns_rr_free(rr); + + rr = ldns_rr_list_pop_rr(rrs); + } + + return 0; +} + +int compare_zones(knot_zone_contents_t *zone, + ldns_rr_list *ldns_list, char verbose) +{ + /* TODO currently test fail when encountering first error - + * it should finish going through the zone */ + knot_rrset_t *tmp_rrset = NULL; + + knot_dname_t *tmp_dname = NULL; + + knot_node_t *node = NULL; + + ldns_rr_list *ldns_rrset = ldns_rr_list_pop_rrset(ldns_list); + + if (ldns_rrset == NULL) { + diag("Error: empty node"); + return 1; + } + + ldns_rr *rr = NULL; + + /* + * Following cycle works like this: First, we get RR from ldns rrset, + * then we search for the node containing the rrset, then we get the + * rrset, which is then compared with whole ldns rrset. + */ + + /* ldns_rr_list_pop_rrset should pop the first rrset */ + while (ldns_rrset != NULL) { + rr = ldns_rr_list_rr(ldns_rrset, 0); + tmp_dname = + knot_dname_new_from_wire(ldns_rdf_data(ldns_rr_owner(rr)), + ldns_rdf_size(ldns_rr_owner(rr)), + NULL); + + node = knot_zone_contents_get_node(zone, tmp_dname); + + if (node == NULL) { + node = knot_zone_contents_get_nsec3_node(zone, + tmp_dname); + } + + if (node == NULL) { + diag("Could not find node"); + diag("%s", knot_dname_to_str(tmp_dname)); + return 1; + } + + knot_dname_free(&tmp_dname); + + tmp_rrset = knot_node_get_rrset(node, + ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset, + 0))); + + if (tmp_rrset == NULL && + (uint)(ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset, 0))) != + (uint)KNOT_RRTYPE_RRSIG) { + diag("Could not find rrset"); + if (!verbose) { + return 1; + } + ldns_rr_list_print(stdout, ldns_rrset); + diag("%s", knot_dname_to_str(node->owner)); + return 1; + } else if ((uint)(ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset, + 0))) == + (uint)KNOT_RRTYPE_RRSIG) { + knot_rrset_t *rrsigs = NULL; + /* read type covered from ldns rrset */ + for (int i = 0; i < ldns_rrset->_rr_count; i++) { + uint16_t type_covered = + ldns_rdf_data(ldns_rr_rdf( + ldns_rr_list_rr(ldns_rrset, i), 0))[1]; + + /* + * Dnslib stores RRSIGs separately - + * we have to find get it from its "parent" + * rrset. + */ + + tmp_rrset = knot_node_get_rrset(node, + type_covered); + + if (tmp_rrset == NULL) { + if (!verbose) { + return 1; + } + diag("following rrset " + "could not be found"); + ldns_rr_list_print(stdout, ldns_rrset); + return 1; + } + + if (rrsigs == NULL) { + rrsigs = tmp_rrset->rrsigs; + } else { + knot_rrset_merge((void *)&rrsigs, + (void *)&(tmp_rrset->rrsigs)); + } + } + tmp_rrset = rrsigs; + } + +/* diag("dnslib type: %d", tmp_rrset->type); + diag("dnslib dname: %s", tmp_rrset->owner->name); + + diag("ldns type: %d", + ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset, 0))); + diag("ldns dname : %s", ldns_rdf_data(ldns_rr_owner( + ldns_rr_list_rr(ldns_rrset, 0)))); */ + +// knot_rrset_dump(tmp_rrset, 1); + + if (compare_rrset_w_ldns_rrset(tmp_rrset, ldns_rrset, + 1, 0) != 0) { + diag("RRSets did not match"); +// knot_rrset_dump(tmp_rrset, 1); + return 1; + } + + ldns_rr_list_deep_free(ldns_rrset); + + ldns_rrset = ldns_rr_list_pop_rrset(ldns_list); + + if (ldns_rrset == NULL) { + ldns_rrset = ldns_rr_list_pop_rrset(ldns_list); + } + } + + return 0; +} + +#endif + +static int test_zoneparser_zone_read(const char *origin, const char *filename, + const char *outfile) +{ +#ifndef TEST_WITH_LDNS + diag("Zoneparser tests without usage of ldns are not implemented"); + return 0; +#endif + +#ifdef TEST_WITH_LDNS + /* Calls zcompile. */ + parser = zparser_create(); + int ret = zone_read(origin, filename, outfile, 0); + if (ret != 0) { + diag("Could not load zone from file: %s", filename); + return 0; + } + + knot_zone_t *dnsl_zone = NULL; + zloader_t *loader = NULL; + if (knot_zload_open(&loader, outfile) != 0) { + diag("Could not create zone loader.\n"); + return 0; + } + dnsl_zone = knot_zload_load(loader); + remove(outfile); + if (!dnsl_zone) { + diag("Could not load dumped zone.\n"); + return 0; + } + + ldns_zone *ldns_zone = NULL; + FILE *f = fopen(filename, "r"); + if (ldns_zone_new_frm_fp(&ldns_zone, f, NULL, + 0, LDNS_RR_CLASS_IN) != LDNS_STATUS_OK) { + diag("Could not load zone from file: %s (ldns)", filename); + return 0; + } + +// ldns_zone_sort(ldns_zone); + + /* + * LDNS stores SOA record independently - create a list with all + * records in it. + */ + + ldns_rr_list *ldns_list = ldns_zone_rrs(ldns_zone); + + ldns_rr_list_push_rr(ldns_list, ldns_zone_soa(ldns_zone)); + + if (compare_zones(dnsl_zone->contents, ldns_list, 0) != 0) { + return 0; + } + + knot_zone_deep_free(&dnsl_zone, 0); + ldns_zone_free(ldns_zone); + fclose(f); + return 1; +#endif +} + +static const int ZONEPARSER_TEST_COUNT = 1; + +/*! API: return number of tests. */ +static int zoneparser_tests_count(int argc, char *argv[]) +{ + return ZONEPARSER_TEST_COUNT; +} + +/*! API: run tests. */ +static int zoneparser_tests_run(int argc, char *argv[]) +{ + if (argc == 3) { + ok(test_zoneparser_zone_read(argv[1], argv[2], + "foo_test_zone"), + "zoneparser: read (%s)", + argv[2]); + } else { + diag("Wrong parameters\n usage: " + "knot-zcompile-unittests origin zonefile"); + return 0; + } + return 1; +} |