1 /* $NetBSD: zt_test.c,v 1.1.1.4 2014/12/10 03:34:43 christos Exp $ */
2
3 /*
4 * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /* Id */
20
21 /*! \file */
22
23 #include <config.h>
24
25 #include <atf-c.h>
26
27 #include <unistd.h>
28
29 #include <isc/app.h>
30 #include <isc/buffer.h>
31 #include <isc/task.h>
32 #include <isc/timer.h>
33
34 #include <dns/db.h>
35 #include <dns/name.h>
36 #include <dns/view.h>
37 #include <dns/zone.h>
38 #include <dns/zt.h>
39
40 #include "dnstest.h"
41
42 struct args {
43 void *arg1;
44 void *arg2;
45 };
46
47 /*
48 * Helper functions
49 */
50 static isc_result_t
count_zone(dns_zone_t * zone,void * uap)51 count_zone(dns_zone_t *zone, void *uap) {
52 int *nzones = (int *)uap;
53
54 UNUSED(zone);
55
56 *nzones += 1;
57 return (ISC_R_SUCCESS);
58 }
59
60 static isc_result_t
load_done(dns_zt_t * zt,dns_zone_t * zone,isc_task_t * task)61 load_done(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
62 /* We treat zt as a pointer to a boolean for testing purposes */
63 isc_boolean_t *done = (isc_boolean_t *) zt;
64
65 UNUSED(zone);
66 UNUSED(task);
67
68 *done = ISC_TRUE;
69 isc_app_shutdown();
70 return (ISC_R_SUCCESS);
71 }
72
73 static isc_result_t
all_done(void * arg)74 all_done(void *arg) {
75 isc_boolean_t *done = (isc_boolean_t *) arg;
76
77 *done = ISC_TRUE;
78 isc_app_shutdown();
79 return (ISC_R_SUCCESS);
80 }
81
82 static void
start_zt_asyncload(isc_task_t * task,isc_event_t * event)83 start_zt_asyncload(isc_task_t *task, isc_event_t *event) {
84 struct args *args = (struct args *)(event->ev_arg);
85
86 UNUSED(task);
87
88 dns_zt_asyncload(args->arg1, all_done, args->arg2);
89
90 isc_event_free(&event);
91 }
92
93 static void
start_zone_asyncload(isc_task_t * task,isc_event_t * event)94 start_zone_asyncload(isc_task_t *task, isc_event_t *event) {
95 struct args *args = (struct args *)(event->ev_arg);
96
97 UNUSED(task);
98
99 dns_zone_asyncload(args->arg1, load_done, args->arg2);
100 isc_event_free(&event);
101 }
102
103 /*
104 * Individual unit tests
105 */
106 ATF_TC(apply);
ATF_TC_HEAD(apply,tc)107 ATF_TC_HEAD(apply, tc) {
108 atf_tc_set_md_var(tc, "descr", "apply a function to a zone table");
109 }
ATF_TC_BODY(apply,tc)110 ATF_TC_BODY(apply, tc) {
111 isc_result_t result;
112 dns_zone_t *zone = NULL;
113 dns_view_t *view = NULL;
114 int nzones = 0;
115
116 UNUSED(tc);
117
118 result = dns_test_begin(NULL, ISC_TRUE);
119 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
120
121 result = dns_test_makezone("foo", &zone, NULL, ISC_TRUE);
122 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
123
124 view = dns_zone_getview(zone);
125 ATF_REQUIRE(view->zonetable != NULL);
126
127 ATF_CHECK_EQ(0, nzones);
128 result = dns_zt_apply(view->zonetable, ISC_FALSE, count_zone, &nzones);
129 ATF_CHECK_EQ(result, ISC_R_SUCCESS);
130 ATF_CHECK_EQ(1, nzones);
131
132 /* These steps are necessary so the zone can be detached properly */
133 result = dns_test_setupzonemgr();
134 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
135 result = dns_test_managezone(zone);
136 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
137 dns_test_releasezone(zone);
138 dns_test_closezonemgr();
139
140 /* The view was left attached in dns_test_makezone() */
141 dns_view_detach(&view);
142 dns_zone_detach(&zone);
143
144 dns_test_end();
145 }
146
147 ATF_TC(asyncload_zone);
ATF_TC_HEAD(asyncload_zone,tc)148 ATF_TC_HEAD(asyncload_zone, tc) {
149 atf_tc_set_md_var(tc, "descr", "asynchronous zone load");
150 }
ATF_TC_BODY(asyncload_zone,tc)151 ATF_TC_BODY(asyncload_zone, tc) {
152 isc_result_t result;
153 dns_zone_t *zone = NULL;
154 dns_view_t *view = NULL;
155 dns_db_t *db = NULL;
156 isc_boolean_t done = ISC_FALSE;
157 int i = 0;
158 struct args args;
159
160 UNUSED(tc);
161
162 result = dns_test_begin(NULL, ISC_TRUE);
163 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
164
165 result = dns_test_makezone("foo", &zone, NULL, ISC_TRUE);
166 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
167
168 result = dns_test_setupzonemgr();
169 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
170 result = dns_test_managezone(zone);
171 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
172
173 view = dns_zone_getview(zone);
174 ATF_REQUIRE(view->zonetable != NULL);
175
176 ATF_CHECK(!dns__zone_loadpending(zone));
177 ATF_CHECK(!done);
178 dns_zone_setfile(zone, "testdata/zt/zone1.db");
179
180 args.arg1 = zone;
181 args.arg2 = &done;
182 isc_app_onrun(mctx, maintask, start_zone_asyncload, &args);
183
184 isc_app_run();
185 while (dns__zone_loadpending(zone) && i++ < 5000)
186 dns_test_nap(1000);
187 ATF_CHECK(done);
188
189 /* The zone should now be loaded; test it */
190 result = dns_zone_getdb(zone, &db);
191 ATF_CHECK_EQ(result, ISC_R_SUCCESS);
192 ATF_CHECK(db != NULL);
193 if (db != NULL)
194 dns_db_detach(&db);
195
196 dns_test_releasezone(zone);
197 dns_test_closezonemgr();
198
199 dns_zone_detach(&zone);
200 dns_view_detach(&view);
201
202 dns_test_end();
203 }
204
205 ATF_TC(asyncload_zt);
ATF_TC_HEAD(asyncload_zt,tc)206 ATF_TC_HEAD(asyncload_zt, tc) {
207 atf_tc_set_md_var(tc, "descr", "asynchronous zone table load");
208 }
ATF_TC_BODY(asyncload_zt,tc)209 ATF_TC_BODY(asyncload_zt, tc) {
210 isc_result_t result;
211 dns_zone_t *zone1 = NULL, *zone2 = NULL, *zone3 = NULL;
212 dns_view_t *view;
213 dns_zt_t *zt;
214 dns_db_t *db = NULL;
215 isc_boolean_t done = ISC_FALSE;
216 int i = 0;
217 struct args args;
218
219 UNUSED(tc);
220
221 result = dns_test_begin(NULL, ISC_TRUE);
222 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
223
224 result = dns_test_makezone("foo", &zone1, NULL, ISC_TRUE);
225 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
226 dns_zone_setfile(zone1, "testdata/zt/zone1.db");
227 view = dns_zone_getview(zone1);
228
229 result = dns_test_makezone("bar", &zone2, view, ISC_TRUE);
230 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
231 dns_zone_setfile(zone2, "testdata/zt/zone1.db");
232
233 /* This one will fail to load */
234 result = dns_test_makezone("fake", &zone3, view, ISC_TRUE);
235 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
236 dns_zone_setfile(zone3, "testdata/zt/nonexistent.db");
237
238 zt = view->zonetable;
239 ATF_REQUIRE(zt != NULL);
240
241 result = dns_test_setupzonemgr();
242 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
243 result = dns_test_managezone(zone1);
244 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
245 result = dns_test_managezone(zone2);
246 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
247 result = dns_test_managezone(zone3);
248 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
249
250 ATF_CHECK(!dns__zone_loadpending(zone1));
251 ATF_CHECK(!dns__zone_loadpending(zone2));
252 ATF_CHECK(!done);
253
254 args.arg1 = zt;
255 args.arg2 = &done;
256 isc_app_onrun(mctx, maintask, start_zt_asyncload, &args);
257
258 isc_app_run();
259 while (!done && i++ < 5000)
260 dns_test_nap(1000);
261 ATF_CHECK(done);
262
263 /* Both zones should now be loaded; test them */
264 result = dns_zone_getdb(zone1, &db);
265 ATF_CHECK_EQ(result, ISC_R_SUCCESS);
266 ATF_CHECK(db != NULL);
267 if (db != NULL)
268 dns_db_detach(&db);
269
270 result = dns_zone_getdb(zone2, &db);
271 ATF_CHECK_EQ(result, ISC_R_SUCCESS);
272 ATF_CHECK(db != NULL);
273 if (db != NULL)
274 dns_db_detach(&db);
275
276 dns_test_releasezone(zone3);
277 dns_test_releasezone(zone2);
278 dns_test_releasezone(zone1);
279 dns_test_closezonemgr();
280
281 dns_zone_detach(&zone1);
282 dns_zone_detach(&zone2);
283 dns_zone_detach(&zone3);
284 dns_view_detach(&view);
285
286 dns_test_end();
287 }
288
289 /*
290 * Main
291 */
ATF_TP_ADD_TCS(tp)292 ATF_TP_ADD_TCS(tp) {
293 ATF_TP_ADD_TC(tp, apply);
294 ATF_TP_ADD_TC(tp, asyncload_zone);
295 ATF_TP_ADD_TC(tp, asyncload_zt);
296 return (atf_no_error());
297 }
298