1/* 2 * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19/*! \file */ 20 21#include <config.h> 22 23#include <atf-c.h> 24 25#include <unistd.h> 26#include <stdlib.h> 27 28#include <dns/db.h> 29#include <dns/dbiterator.h> 30#include <dns/name.h> 31 32#include "dnstest.h" 33 34/* 35 * Helper functions 36 */ 37 38#define BUFLEN 255 39#define BIGBUFLEN (64 * 1024) 40#define TEST_ORIGIN "test" 41 42static isc_result_t 43setup_db(const char *testfile, dns_dbtype_t dbtype, dns_db_t **db) { 44 isc_result_t result; 45 int len; 46 char origin[sizeof(TEST_ORIGIN)]; 47 dns_name_t dns_origin; 48 isc_buffer_t source; 49 isc_buffer_t target; 50 unsigned char name_buf[BUFLEN]; 51 52 strcpy(origin, TEST_ORIGIN); 53 len = strlen(origin); 54 isc_buffer_init(&source, origin, len); 55 isc_buffer_add(&source, len); 56 isc_buffer_setactive(&source, len); 57 isc_buffer_init(&target, name_buf, BUFLEN); 58 dns_name_init(&dns_origin, NULL); 59 60 result = dns_name_fromtext(&dns_origin, &source, dns_rootname, 61 0, &target); 62 if (result != ISC_R_SUCCESS) 63 return(result); 64 65 result = dns_db_create(mctx, "rbt", &dns_origin, dbtype, 66 dns_rdataclass_in, 0, NULL, db); 67 if (result != ISC_R_SUCCESS) 68 return (result); 69 70 /* 71 * atf-run changes us to a /tmp directory, so tests 72 * that access test data files must first chdir to the proper 73 * location. 74 */ 75 if (chdir(TESTS) == -1) 76 return (ISC_R_FAILURE); 77 78 result = dns_db_load(*db, testfile); 79 return (result); 80} 81 82static isc_result_t 83make_name(const char *src, dns_name_t *name) { 84 isc_buffer_t b; 85 isc_buffer_init(&b, src, strlen(src)); 86 isc_buffer_add(&b, strlen(src)); 87 return (dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 88} 89 90/* 91 * Individual unit tests 92 */ 93 94/* create: make sure we can create a dbiterator */ 95static void 96test_create(const atf_tc_t *tc) { 97 isc_result_t result; 98 dns_db_t *db = NULL; 99 dns_dbiterator_t *iter = NULL; 100 101 result = dns_test_begin(NULL, ISC_FALSE); 102 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 103 104 result = setup_db(atf_tc_get_md_var(tc, "X-filename"), 105 dns_dbtype_cache, &db); 106 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 107 108 result = dns_db_createiterator(db, 0, &iter); 109 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 110 111 dns_dbiterator_destroy(&iter); 112 dns_db_detach(&db); 113 dns_test_end(); 114} 115 116ATF_TC(create); 117ATF_TC_HEAD(create, tc) { 118 atf_tc_set_md_var(tc, "descr", "create a database iterator"); 119 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); 120} 121ATF_TC_BODY(create, tc) { 122 test_create(tc); 123} 124 125ATF_TC(create_nsec3); 126ATF_TC_HEAD(create_nsec3, tc) { 127 atf_tc_set_md_var(tc, "descr", "create a database iterator (NSEC3)"); 128 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); 129} 130ATF_TC_BODY(create_nsec3, tc) { 131 test_create(tc); 132} 133 134/* walk: walk a database */ 135static void 136test_walk(const atf_tc_t *tc) { 137 isc_result_t result; 138 dns_db_t *db = NULL; 139 dns_dbiterator_t *iter = NULL; 140 dns_dbnode_t *node = NULL; 141 dns_name_t *name; 142 dns_fixedname_t f; 143 int i = 0; 144 145 UNUSED(tc); 146 147 dns_fixedname_init(&f); 148 name = dns_fixedname_name(&f); 149 150 result = dns_test_begin(NULL, ISC_FALSE); 151 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 152 153 result = setup_db(atf_tc_get_md_var(tc, "X-filename"), 154 dns_dbtype_cache, &db); 155 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 156 157 result = dns_db_createiterator(db, 0, &iter); 158 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 159 160 for (result = dns_dbiterator_first(iter); 161 result == ISC_R_SUCCESS; 162 result = dns_dbiterator_next(iter)) { 163 result = dns_dbiterator_current(iter, &node, name); 164 if (result == DNS_R_NEWORIGIN) 165 result = ISC_R_SUCCESS; 166 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 167 dns_db_detachnode(db, &node); 168 i++; 169 } 170 171 ATF_CHECK_EQ(i, atoi(atf_tc_get_md_var(tc, "X-nodes"))); 172 173 dns_dbiterator_destroy(&iter); 174 dns_db_detach(&db); 175 dns_test_end(); 176} 177 178ATF_TC(walk); 179ATF_TC_HEAD(walk, tc) { 180 atf_tc_set_md_var(tc, "descr", "walk database"); 181 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); 182 atf_tc_set_md_var(tc, "X-nodes", "12"); 183} 184ATF_TC_BODY(walk, tc) { 185 test_walk(tc); 186} 187 188ATF_TC(walk_nsec3); 189ATF_TC_HEAD(walk_nsec3, tc) { 190 atf_tc_set_md_var(tc, "descr", "walk database"); 191 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); 192 atf_tc_set_md_var(tc, "X-nodes", "33"); 193} 194ATF_TC_BODY(walk_nsec3, tc) { 195 test_walk(tc); 196} 197 198/* reverse: walk database backwards */ 199static void test_reverse(const atf_tc_t *tc) { 200 isc_result_t result; 201 dns_db_t *db = NULL; 202 dns_dbiterator_t *iter = NULL; 203 dns_dbnode_t *node = NULL; 204 dns_name_t *name; 205 dns_fixedname_t f; 206 int i = 0; 207 208 UNUSED(tc); 209 210 dns_fixedname_init(&f); 211 name = dns_fixedname_name(&f); 212 213 result = dns_test_begin(NULL, ISC_FALSE); 214 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 215 216 result = setup_db(atf_tc_get_md_var(tc, "X-filename"), 217 dns_dbtype_cache, &db); 218 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 219 220 result = dns_db_createiterator(db, 0, &iter); 221 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 222 223 for (result = dns_dbiterator_last(iter); 224 result == ISC_R_SUCCESS; 225 result = dns_dbiterator_prev(iter)) { 226 result = dns_dbiterator_current(iter, &node, name); 227 if (result == DNS_R_NEWORIGIN) 228 result = ISC_R_SUCCESS; 229 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 230 dns_db_detachnode(db, &node); 231 i++; 232 } 233 234 ATF_CHECK_EQ(i, 12); 235 236 dns_dbiterator_destroy(&iter); 237 dns_db_detach(&db); 238 dns_test_end(); 239} 240 241ATF_TC(reverse); 242ATF_TC_HEAD(reverse, tc) { 243 atf_tc_set_md_var(tc, "descr", "walk database backwards"); 244 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); 245} 246ATF_TC_BODY(reverse, tc) { 247 test_reverse(tc); 248} 249 250ATF_TC(reverse_nsec3); 251ATF_TC_HEAD(reverse_nsec3, tc) { 252 atf_tc_set_md_var(tc, "descr", "walk database backwards"); 253 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); 254} 255ATF_TC_BODY(reverse_nsec3, tc) { 256 test_reverse(tc); 257} 258 259/* seek: walk database starting at a particular node */ 260static void test_seek(const atf_tc_t *tc) { 261 isc_result_t result; 262 dns_db_t *db = NULL; 263 dns_dbiterator_t *iter = NULL; 264 dns_dbnode_t *node = NULL; 265 dns_name_t *name, *seekname; 266 dns_fixedname_t f1, f2; 267 int i = 0; 268 269 UNUSED(tc); 270 271 dns_fixedname_init(&f1); 272 name = dns_fixedname_name(&f1); 273 dns_fixedname_init(&f2); 274 seekname = dns_fixedname_name(&f2); 275 276 result = dns_test_begin(NULL, ISC_FALSE); 277 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 278 279 result = setup_db(atf_tc_get_md_var(tc, "X-filename"), 280 dns_dbtype_cache, &db); 281 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 282 283 result = dns_db_createiterator(db, 0, &iter); 284 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 285 286 result = make_name("c." TEST_ORIGIN, seekname); 287 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 288 289 result = dns_dbiterator_seek(iter, seekname); 290 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 291 292 while (result == ISC_R_SUCCESS) { 293 result = dns_dbiterator_current(iter, &node, name); 294 if (result == DNS_R_NEWORIGIN) 295 result = ISC_R_SUCCESS; 296 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 297 dns_db_detachnode(db, &node); 298 result = dns_dbiterator_next(iter); 299 i++; 300 } 301 302 ATF_CHECK_EQ(i, atoi(atf_tc_get_md_var(tc, "X-nodes"))); 303 304 dns_dbiterator_destroy(&iter); 305 dns_db_detach(&db); 306 dns_test_end(); 307} 308 309ATF_TC(seek); 310ATF_TC_HEAD(seek, tc) { 311 atf_tc_set_md_var(tc, "descr", "walk database starting at " 312 "a particular node"); 313 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); 314 atf_tc_set_md_var(tc, "X-nodes", "9"); 315} 316ATF_TC_BODY(seek, tc) { 317 test_seek(tc); 318} 319 320ATF_TC(seek_nsec3); 321ATF_TC_HEAD(seek_nsec3, tc) { 322 atf_tc_set_md_var(tc, "descr", "walk database starting at " 323 "a particular node"); 324 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); 325 atf_tc_set_md_var(tc, "X-nodes", "30"); 326} 327ATF_TC_BODY(seek_nsec3, tc) { 328 test_seek(tc); 329} 330 331/* 332 * seek_emty: walk database starting at an empty nonterminal node 333 * (should fail) 334 */ 335static void test_seek_empty(const atf_tc_t *tc) { 336 isc_result_t result; 337 dns_db_t *db = NULL; 338 dns_dbiterator_t *iter = NULL; 339 dns_name_t *seekname; 340 dns_fixedname_t f1; 341 342 UNUSED(tc); 343 344 dns_fixedname_init(&f1); 345 seekname = dns_fixedname_name(&f1); 346 347 result = dns_test_begin(NULL, ISC_FALSE); 348 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 349 350 result = setup_db(atf_tc_get_md_var(tc, "X-filename"), 351 dns_dbtype_cache, &db); 352 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 353 354 result = dns_db_createiterator(db, 0, &iter); 355 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 356 357 result = make_name("d." TEST_ORIGIN, seekname); 358 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 359 360 result = dns_dbiterator_seek(iter, seekname); 361 ATF_CHECK_EQ(result, ISC_R_NOTFOUND); 362 363 dns_dbiterator_destroy(&iter); 364 dns_db_detach(&db); 365 dns_test_end(); 366} 367 368ATF_TC(seek_empty); 369ATF_TC_HEAD(seek_empty, tc) { 370 atf_tc_set_md_var(tc, "descr", "walk database starting at an " 371 "empty nonterminal node"); 372 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); 373} 374ATF_TC_BODY(seek_empty, tc) { 375 test_seek_empty(tc); 376} 377 378ATF_TC(seek_empty_nsec3); 379ATF_TC_HEAD(seek_empty_nsec3, tc) { 380 atf_tc_set_md_var(tc, "descr", "walk database starting at an " 381 "empty nonterminal node"); 382 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); 383} 384ATF_TC_BODY(seek_empty_nsec3, tc) { 385 test_seek_empty(tc); 386} 387 388/* 389 * seek_emty: walk database starting at an empty nonterminal node 390 * (should fail) 391 */ 392static void test_seek_nx(const atf_tc_t *tc) { 393 isc_result_t result; 394 dns_db_t *db = NULL; 395 dns_dbiterator_t *iter = NULL; 396 dns_name_t *seekname; 397 dns_fixedname_t f1; 398 399 UNUSED(tc); 400 401 dns_fixedname_init(&f1); 402 seekname = dns_fixedname_name(&f1); 403 404 result = dns_test_begin(NULL, ISC_FALSE); 405 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 406 407 result = setup_db(atf_tc_get_md_var(tc, "X-filename"), 408 dns_dbtype_cache, &db); 409 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 410 411 result = dns_db_createiterator(db, 0, &iter); 412 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 413 414 result = make_name("nonexistent." TEST_ORIGIN, seekname); 415 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 416 417 result = dns_dbiterator_seek(iter, seekname); 418 ATF_CHECK_EQ(result, ISC_R_NOTFOUND); 419 420 dns_dbiterator_destroy(&iter); 421 dns_db_detach(&db); 422 dns_test_end(); 423} 424 425ATF_TC(seek_nx); 426ATF_TC_HEAD(seek_nx, tc) { 427 atf_tc_set_md_var(tc, "descr", "attempt to walk database starting " 428 "at a nonexistent node"); 429 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); 430} 431ATF_TC_BODY(seek_nx, tc) { 432 test_seek_nx(tc); 433} 434 435ATF_TC(seek_nx_nsec3); 436ATF_TC_HEAD(seek_nx_nsec3, tc) { 437 atf_tc_set_md_var(tc, "descr", "attempt to walk database starting " 438 "at a nonexistent node"); 439 atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); 440} 441ATF_TC_BODY(seek_nx_nsec3, tc) { 442 test_seek_nx(tc); 443} 444 445/* 446 * Main 447 */ 448ATF_TP_ADD_TCS(tp) { 449 ATF_TP_ADD_TC(tp, create); 450 ATF_TP_ADD_TC(tp, create_nsec3); 451 ATF_TP_ADD_TC(tp, walk); 452 ATF_TP_ADD_TC(tp, walk_nsec3); 453 ATF_TP_ADD_TC(tp, reverse); 454 ATF_TP_ADD_TC(tp, reverse_nsec3); 455 ATF_TP_ADD_TC(tp, seek); 456 ATF_TP_ADD_TC(tp, seek_nsec3); 457 ATF_TP_ADD_TC(tp, seek_empty); 458 ATF_TP_ADD_TC(tp, seek_empty_nsec3); 459 ATF_TP_ADD_TC(tp, seek_nx); 460 ATF_TP_ADD_TC(tp, seek_nx_nsec3); 461 return (atf_no_error()); 462} 463 464/* 465 * XXX: 466 * dns_dbiterator API calls that are not yet part of this unit test: 467 * 468 * dns_dbiterator_pause 469 * dns_dbiterator_origin 470 * dns_dbiterator_setcleanmode 471 */ 472