1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
/* Copyright (C) CZ.NIC, z.s.p.o. and contributors
* SPDX-License-Identifier: GPL-2.0-or-later
* For more information, see <https://www.knot-dns.cz/>
*/
#include <assert.h>
#include <tap/basic.h>
#include <string.h>
#include "libknot/rdataset.c"
#include "libknot/libknot.h"
// Inits rdataset with given rdata.
#define RDATASET_INIT_WITH(set, rdata) \
knot_rdataset_clear(&set, NULL); \
ret = knot_rdataset_add(&set, rdata, NULL); \
assert(ret == KNOT_EOK);
static size_t rdataset_size(const knot_rdataset_t *rrs)
{
if (rrs == NULL || rrs->count == 0) {
return 0;
}
const knot_rdata_t *last = rr_seek(rrs, rrs->count - 1);
return (uint8_t *)last + knot_rdata_size(last->len) - (uint8_t *)rrs->rdata;
}
int main(int argc, char *argv[])
{
plan_lazy();
// Test init
knot_rdataset_t rdataset;
knot_rdataset_init(&rdataset);
ok(rdataset.rdata == NULL && rdataset.count == 0 && rdataset.size == 0, "rdataset: init.");
// Test rdata addition
uint8_t buf_gt[knot_rdata_size(4)];
knot_rdata_t *rdata_gt = (knot_rdata_t *)buf_gt;
knot_rdata_init(rdata_gt, 4, (uint8_t *)"wxyz");
int ret = knot_rdataset_add(NULL, NULL, NULL);
is_int(KNOT_EINVAL, ret, "rdataset: add NULL.");
ret = knot_rdataset_add(&rdataset, rdata_gt, NULL);
bool add_ok = ret == KNOT_EOK && rdataset.count == 1 &&
knot_rdata_cmp(rdata_gt, rdataset.rdata) == 0;
ok(add_ok, "rdataset: add.");
uint8_t buf_lo[knot_rdata_size(4)];
knot_rdata_t *rdata_lo = (knot_rdata_t *)buf_lo;
knot_rdata_init(rdata_lo, 4, (uint8_t *)"abcd");
ret = knot_rdataset_add(&rdataset, rdata_lo, NULL);
add_ok = ret == KNOT_EOK && rdataset.count == 2 &&
knot_rdata_cmp(rdata_lo, rdataset.rdata) == 0;
ok(add_ok, "rdataset: add lower.");
// Test getters
ok(knot_rdata_cmp(knot_rdataset_at(&rdataset, 0), rdata_lo) == 0 &&
knot_rdata_cmp(knot_rdataset_at(&rdataset, 1), rdata_gt) == 0,
"rdataset: at.");
ok(rdataset_size(&rdataset) == knot_rdata_size(4) * 2,
"rdataset: size.");
ok(rdataset.size == rdataset_size(&rdataset), "rdataset: size precomputed (%u %zu).",
rdataset.size, rdataset_size(&rdataset));
// Test copy
ok(knot_rdataset_copy(NULL, NULL, NULL) == KNOT_EINVAL,
"rdataset: copy NULL.");
knot_rdataset_t copy;
ret = knot_rdataset_copy(©, &rdataset, NULL);
const bool copy_ok = ret == KNOT_EOK && copy.count == rdataset.count &&
rdataset_size(©) == rdataset_size(&rdataset) &&
rdataset.rdata != NULL && copy.rdata != NULL &&
memcmp(rdataset.rdata, copy.rdata,
rdataset_size(&rdataset)) == 0;
ok(copy_ok, "rdataset: copy");
ok(copy.size == rdataset_size(©), "copy: size precomputed.");
// Test eq
ok(knot_rdataset_eq(&rdataset, ©), "rdataset: equal");
// Test clear
knot_rdataset_clear(©, NULL);
ok(copy.count == 0 && copy.rdata == NULL, "rdataset: clear.");
// Test not equal (different count)
ok(!knot_rdataset_eq(&rdataset, ©), "rdataset: not equal - count");
// Test member
uint8_t buf_not[knot_rdata_size(1)];
knot_rdata_t *not_a_member = (knot_rdata_t *)buf_not;
knot_rdata_init(not_a_member, 1, (uint8_t *)"?");
ok(knot_rdataset_member(&rdataset, rdata_gt), "rdataset: is member.");
ok(!knot_rdataset_member(&rdataset, not_a_member), "rdataset: is not member.");
// Test merge
ok(knot_rdataset_merge(NULL, NULL, NULL) == KNOT_EINVAL,
"rdataset: merge NULL.");
knot_rdataset_t empty;
knot_rdataset_init(&empty);
ret = knot_rdataset_merge(&empty, &rdataset, NULL);
bool merge_ok = ret == KNOT_EOK && knot_rdataset_eq(&empty, &rdataset);
ok(merge_ok, "rdataset: merge empty.");
knot_rdata_t *data_before = rdataset.rdata;
ret = knot_rdataset_merge(&rdataset, &rdataset, NULL);
merge_ok = ret == KNOT_EOK && rdataset.count == 2 &&
data_before == rdataset.rdata;
ok(merge_ok, "rdataset: merge self.");
knot_rdataset_clear(&empty, NULL);
// Init structs for merge sort testing
knot_rdataset_t rdataset_lo; // "Lower" rdataset
knot_rdataset_init(&rdataset_lo);
RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
knot_rdataset_t rdataset_gt; // "Greater" rdataset
knot_rdataset_init(&rdataset_gt);
RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
// Test not equal - different data
ok(!knot_rdataset_eq(&rdataset_gt, &rdataset_lo), "rdataset: data not equal.");
// Test that merge keeps the sorted order
ret = knot_rdataset_merge(&rdataset_lo, &rdataset_gt, NULL);
merge_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset_lo, &rdataset);
ok(merge_ok, "rdataset: merge into lower.");
RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
ret = knot_rdataset_merge(&rdataset_gt, &rdataset_lo, NULL);
merge_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset_gt, &rdataset);
ok(merge_ok, "rdataset: merge into greater.");
// Test intersect
ok(knot_rdataset_intersect(NULL, NULL, NULL, NULL) == KNOT_EINVAL,
"rdataset: intersect NULL.");
knot_rdataset_t intersection;
ret = knot_rdataset_intersect(&rdataset, &rdataset, &intersection, NULL);
bool intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset, &intersection);
ok(intersect_ok, "rdataset: intersect self.");
knot_rdataset_clear(&intersection, NULL);
RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
ret = knot_rdataset_intersect(&rdataset_lo, &rdataset_gt, &intersection, NULL);
intersect_ok = ret == KNOT_EOK && intersection.count == 0;
ok(intersect_ok, "rdataset: intersect no common.");
ret = knot_rdataset_intersect(&rdataset, &rdataset_lo, &intersection, NULL);
intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(&intersection, &rdataset_lo);
ok(intersect_ok, "rdataset: intersect normal.");
knot_rdataset_clear(&intersection, NULL);
// Test intersect2
ok(knot_rdataset_intersect2(NULL, NULL, NULL) == KNOT_EINVAL,
"rdataset: intersect2 NULL.");
ret = knot_rdataset_intersect2(&rdataset, &rdataset, NULL);
intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset, &rdataset);
ok(intersect_ok, "rdataset: intersect2 self.");
knot_rdataset_clear(&intersection, NULL);
RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
ret = knot_rdataset_intersect2(&rdataset_lo, &rdataset_gt, NULL);
intersect_ok = ret == KNOT_EOK && rdataset_lo.count == 0;
ok(intersect_ok, "rdataset: intersect2 no common.");
ret = knot_rdataset_copy(©, &rdataset, NULL);
assert(ret == KNOT_EOK);
ret = knot_rdataset_intersect2(©, &rdataset_lo, NULL);
intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(©, &rdataset_lo);
ok(intersect_ok, "rdataset: intersect2 normal.");
knot_rdataset_clear(©, NULL);
// Test subtract
ok(knot_rdataset_subtract(NULL, NULL, NULL) == KNOT_EINVAL,
"rdataset: subtract NULL.");
ret = knot_rdataset_copy(©, &rdataset, NULL);
assert(ret == KNOT_EOK);
ok(knot_rdataset_subtract(©, ©, NULL) == KNOT_EOK &&
copy.count == 0, "rdataset: subtract self.");
ret = knot_rdataset_copy(©, &rdataset, NULL);
assert(ret == KNOT_EOK);
ret = knot_rdataset_subtract(©, &rdataset, NULL);
bool subtract_ok = ret == KNOT_EOK && copy.count == 0;
ok(subtract_ok, "rdataset: subtract identical.");
RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
data_before = rdataset_lo.rdata;
ret = knot_rdataset_subtract(&rdataset_lo, &rdataset_gt, NULL);
subtract_ok = ret == KNOT_EOK && rdataset_lo.count == 1 &&
rdataset_lo.rdata == data_before;
ok(subtract_ok, "rdataset: subtract no common.");
ret = knot_rdataset_subtract(&rdataset, &rdataset_gt, NULL);
subtract_ok = ret == KNOT_EOK && rdataset.count == 1;
ok(subtract_ok, "rdataset: subtract the second.");
ret = knot_rdataset_subtract(&rdataset, &rdataset_lo, NULL);
subtract_ok = ret == KNOT_EOK && rdataset.count == 0 &&
rdataset.rdata == NULL;
ok(subtract_ok, "rdataset: subtract last.");
knot_rdataset_clear(©, NULL);
knot_rdataset_clear(&rdataset, NULL);
knot_rdataset_clear(&rdataset_lo, NULL);
knot_rdataset_clear(&rdataset_gt, NULL);
return EXIT_SUCCESS;
}
|