7
Martin Nagy <mnagy@redhat.com>
8
Jakub Hrozek <jhrozek@redhat.com>
10
Copyright (C) Red Hat, Inc 2009
12
This program is free software; you can redistribute it and/or modify
13
it under the terms of the GNU General Public License as published by
14
the Free Software Foundation; either version 3 of the License, or
15
(at your option) any later version.
17
This program is distributed in the hope that it will be useful,
18
but WITHOUT ANY WARRANTY; without even the implied warranty of
19
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
GNU General Public License for more details.
22
You should have received a copy of the GNU General Public License
23
along with this program. If not, see <http://www.gnu.org/licenses/>.
32
#include <arpa/inet.h>
34
#include "tests/common.h"
35
#include "util/util.h"
37
/* Interface under test */
38
#include "resolv/async_resolv.h"
40
static int use_net_test;
41
static char *txt_host;
42
static char *srv_host;
44
struct resolv_test_ctx {
45
struct tevent_context *ev;
46
struct resolv_ctx *resolv;
58
static int setup_resolv_test(struct resolv_test_ctx **ctx)
60
struct resolv_test_ctx *test_ctx;
63
test_ctx = talloc_zero(NULL, struct resolv_test_ctx);
64
if (test_ctx == NULL) {
65
fail("Could not allocate memory for test context");
69
test_ctx->ev = tevent_context_init(test_ctx);
70
if (test_ctx->ev == NULL) {
71
fail("Could not init tevent context");
72
talloc_free(test_ctx);
76
ret = resolv_init(test_ctx, test_ctx->ev, 5, &test_ctx->resolv);
78
fail("Could not init resolv context");
79
talloc_free(test_ctx);
87
static int test_loop(struct resolv_test_ctx *data)
90
tevent_loop_once(data->ev);
95
START_TEST(test_copy_hostent)
98
struct hostent *new_he;
100
char name[] = "foo.example.com";
101
char alias_1[] = "bar.example.com";
102
char alias_2[] = "baz.example.com";
103
char *aliases[] = { alias_1, alias_2, NULL };
104
char addr_1[] = { 1, 2, 3, 4 };
105
char addr_2[] = { 4, 3, 2, 1 };
106
char *addr_list[] = { addr_1, addr_2, NULL };
107
struct hostent he = {
108
name, aliases, 123 /* Whatever. */,
109
sizeof(addr_1), addr_list
112
ctx = talloc_new(NULL);
113
fail_if(ctx == NULL);
115
check_leaks_push(ctx);
116
new_he = resolv_copy_hostent(ctx, &he);
117
fail_if(new_he == NULL);
118
fail_if(strcmp(new_he->h_name, name));
119
fail_if(strcmp(new_he->h_aliases[0], alias_1));
120
fail_if(strcmp(new_he->h_aliases[1], alias_2));
121
fail_if(new_he->h_aliases[2] != NULL);
122
fail_if(new_he->h_addrtype != 123);
123
fail_if(new_he->h_length != sizeof(addr_1));
124
fail_if(memcmp(new_he->h_addr_list[0], addr_1, sizeof(addr_1)));
125
fail_if(memcmp(new_he->h_addr_list[1], addr_2, sizeof(addr_1)));
126
fail_if(new_he->h_addr_list[2] != NULL);
129
check_leaks_pop(ctx);
133
static void test_localhost(struct tevent_req *req)
137
struct hostent *hostent;
139
struct resolv_test_ctx *test_ctx = tevent_req_callback_data(req,
140
struct resolv_test_ctx);
142
test_ctx->done = true;
144
recv_status = resolv_gethostbyname_recv(req, test_ctx,
145
&status, NULL, &hostent);
147
if (recv_status != EOK) {
148
DEBUG(2, ("resolv_gethostbyname_recv failed: %d\n", recv_status));
149
test_ctx->error = recv_status;
152
DEBUG(7, ("resolv_gethostbyname_recv status: %d\n", status));
154
test_ctx->error = ENOENT;
155
for (i = 0; hostent->h_addr_list[i]; i++) {
157
inet_ntop(hostent->h_addrtype, hostent->h_addr_list[i], addr_buf, sizeof(addr_buf));
159
/* test that localhost resolves to 127.0.0.1 or ::1 */
160
if (strcmp(addr_buf, "127.0.0.1") == 0 || strcmp(addr_buf, "::1") == 0) {
161
test_ctx->error = EOK;
164
talloc_free(hostent);
167
START_TEST(test_resolv_localhost)
169
struct resolv_test_ctx *test_ctx;
171
struct tevent_req *req;
172
const char *hostname = "localhost.localdomain";
174
ret = setup_resolv_test(&test_ctx);
176
fail("Could not set up test");
180
check_leaks_push(test_ctx);
181
req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
182
DEBUG(7, ("Sent resolv_gethostbyname\n"));
188
tevent_req_set_callback(req, test_localhost, test_ctx);
189
ret = test_loop(test_ctx);
192
check_leaks_pop(test_ctx);
193
fail_unless(ret == EOK);
195
talloc_zfree(test_ctx);
199
static void test_negative(struct tevent_req *req)
203
struct hostent *hostent;
204
struct resolv_test_ctx *test_ctx;
206
test_ctx = tevent_req_callback_data(req, struct resolv_test_ctx);
207
test_ctx->done = true;
209
recv_status = resolv_gethostbyname_recv(req, test_ctx,
210
&status, NULL, &hostent);
212
if (recv_status == EOK) {
213
DEBUG(7, ("resolv_gethostbyname_recv succeeded in a negative test"));
217
test_ctx->error = status;
218
DEBUG(2, ("resolv_gethostbyname_recv status: %d: %s\n", status, resolv_strerror(status)));
221
START_TEST(test_resolv_negative)
224
struct tevent_req *req;
225
const char *hostname = "sssd.foo";
226
struct resolv_test_ctx *test_ctx;
228
ret = setup_resolv_test(&test_ctx);
230
fail("Could not set up test");
234
check_leaks_push(test_ctx);
235
req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
236
DEBUG(7, ("Sent resolv_gethostbyname\n"));
242
tevent_req_set_callback(req, test_negative, test_ctx);
243
ret = test_loop(test_ctx);
246
check_leaks_pop(test_ctx);
248
fail_unless(ret != EOK);
249
fail_unless(test_ctx->error == ARES_ENOTFOUND);
250
talloc_zfree(test_ctx);
254
static void test_internet(struct tevent_req *req)
258
struct resolv_test_ctx *test_ctx;
260
struct hostent *hostent = NULL;
261
struct ares_txt_reply *txt_replies = NULL, *txtptr;
262
struct ares_srv_reply *srv_replies = NULL, *srvptr;
264
test_ctx = tevent_req_callback_data(req, struct resolv_test_ctx);
266
test_ctx->done = true;
268
tmp_ctx = talloc_new(test_ctx);
269
check_leaks_push(tmp_ctx);
271
switch (test_ctx->tested_function) {
272
case TESTING_HOSTNAME:
273
recv_status = resolv_gethostbyname_recv(req, tmp_ctx,
274
&status, NULL, &hostent);
275
test_ctx->error = (hostent->h_length == 0) ? ENOENT : EOK;
278
recv_status = resolv_gettxt_recv(tmp_ctx, req, &status, NULL,
280
test_ctx->error = (txt_replies == NULL) ? ENOENT : EOK;
281
for (txtptr = txt_replies; txtptr != NULL; txtptr = txtptr->next) {
282
DEBUG(2, ("TXT Record: %s\n", txtptr->txt));
286
recv_status = resolv_getsrv_recv(tmp_ctx, req, &status, NULL,
288
test_ctx->error = (srv_replies == NULL) ? ENOENT : EOK;
289
for (srvptr = srv_replies; srvptr != NULL; srvptr = srvptr->next) {
290
DEBUG(2, ("SRV Record: %d %d %d %s\n", srvptr->weight,
291
srvptr->priority, srvptr->port,
297
fail_if(recv_status != EOK, "The recv function failed: %d", recv_status);
298
DEBUG(7, ("recv status: %d\n", status));
300
if (hostent != NULL) {
301
talloc_free(hostent);
302
} else if (txt_replies != NULL) {
303
talloc_free(txt_replies);
304
} else if (srv_replies != NULL) {
305
talloc_free(srv_replies);
307
check_leaks_pop(tmp_ctx);
310
START_TEST(test_resolv_internet)
313
struct tevent_req *req;
314
const char *hostname = "redhat.com";
315
struct resolv_test_ctx *test_ctx;
317
ret = setup_resolv_test(&test_ctx);
319
fail("Could not set up test");
322
test_ctx->tested_function = TESTING_HOSTNAME;
324
check_leaks_push(test_ctx);
325
req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
326
DEBUG(7, ("Sent resolv_gethostbyname\n"));
332
tevent_req_set_callback(req, test_internet, test_ctx);
333
ret = test_loop(test_ctx);
336
fail_unless(ret == EOK);
337
check_leaks_pop(test_ctx);
338
talloc_zfree(test_ctx);
342
START_TEST(test_resolv_internet_txt)
345
struct tevent_req *req;
346
struct resolv_test_ctx *test_ctx;
348
ret = setup_resolv_test(&test_ctx);
349
fail_if(ret != EOK, "Could not set up test");
350
test_ctx->tested_function = TESTING_TXT;
352
check_leaks_push(test_ctx);
354
req = resolv_gettxt_send(test_ctx, test_ctx->ev, test_ctx->resolv, txt_host);
355
fail_if(req == NULL, "Function resolv_gettxt_send failed");
357
tevent_req_set_callback(req, test_internet, test_ctx);
358
ret = test_loop(test_ctx);
359
fail_unless(ret == EOK);
361
check_leaks_pop(test_ctx);
363
talloc_zfree(test_ctx);
367
START_TEST(test_resolv_internet_srv)
370
struct tevent_req *req;
371
struct resolv_test_ctx *test_ctx;
373
ret = setup_resolv_test(&test_ctx);
374
fail_if(ret != EOK, "Could not set up test");
375
test_ctx->tested_function = TESTING_SRV;
377
check_leaks_push(test_ctx);
379
req = resolv_getsrv_send(test_ctx, test_ctx->ev, test_ctx->resolv, srv_host);
380
fail_if(req == NULL, "Function resolv_getsrv_send failed");
382
tevent_req_set_callback(req, test_internet, test_ctx);
383
ret = test_loop(test_ctx);
384
fail_unless(ret == EOK);
386
check_leaks_pop(test_ctx);
388
talloc_zfree(test_ctx);
392
static void resolv_free_context(struct tevent_context *ev,
393
struct tevent_timer *te,
394
struct timeval t, void *ptr)
396
struct resolv_ctx *rctx = talloc_get_type(ptr, struct resolv_ctx);
397
DEBUG(7, ("freeing the context\n"));
402
static void resolv_free_done(struct tevent_context *ev,
403
struct tevent_timer *te,
404
struct timeval t, void *ptr)
406
struct resolv_test_ctx *tctx = talloc_get_type(ptr, struct resolv_test_ctx);
407
DEBUG(7, ("marking test as done\n"));
413
START_TEST(test_resolv_free_context)
416
struct tevent_req *req;
417
const char *hostname = "redhat.com";
418
struct resolv_test_ctx *test_ctx;
419
struct tevent_timer *free_timer, *terminate_timer;
420
struct timeval free_tv, terminate_tv;
422
ret = setup_resolv_test(&test_ctx);
424
fail("Could not set up test");
428
req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
429
DEBUG(7, ("Sent resolv_gethostbyname\n"));
431
fail("Error calling resolv_gethostbyname_send");
435
gettimeofday(&free_tv, NULL);
438
terminate_tv.tv_sec = free_tv.tv_sec + 1;
439
terminate_tv.tv_usec = 0;
441
free_timer = tevent_add_timer(test_ctx->ev, test_ctx, free_tv, resolv_free_context, test_ctx->resolv);
442
if (free_timer == NULL) {
443
fail("Error calling tevent_add_timer");
447
terminate_timer = tevent_add_timer(test_ctx->ev, test_ctx, terminate_tv, resolv_free_done, test_ctx);
448
if (terminate_timer == NULL) {
449
fail("Error calling tevent_add_timer");
453
ret = test_loop(test_ctx);
454
fail_unless(ret == EOK);
457
talloc_zfree(test_ctx);
461
static void resolv_free_req(struct tevent_context *ev,
462
struct tevent_timer *te,
463
struct timeval t, void *ptr)
465
struct tevent_req *req = talloc_get_type(ptr, struct tevent_req);
466
DEBUG(7, ("freeing the request\n"));
471
START_TEST(test_resolv_free_req)
474
struct tevent_req *req;
475
const char *hostname = "redhat.com";
476
struct resolv_test_ctx *test_ctx;
477
struct tevent_timer *free_timer, *terminate_timer;
478
struct timeval free_tv, terminate_tv;
480
ret = setup_resolv_test(&test_ctx);
482
fail("Could not set up test");
486
check_leaks_push(test_ctx);
487
req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
488
DEBUG(7, ("Sent resolv_gethostbyname\n"));
490
fail("Error calling resolv_gethostbyname_send");
494
gettimeofday(&free_tv, NULL);
497
terminate_tv.tv_sec = free_tv.tv_sec + 1;
498
terminate_tv.tv_usec = 0;
500
free_timer = tevent_add_timer(test_ctx->ev, test_ctx, free_tv, resolv_free_req, req);
501
if (free_timer == NULL) {
502
fail("Error calling tevent_add_timer");
506
terminate_timer = tevent_add_timer(test_ctx->ev, test_ctx, terminate_tv, resolv_free_done, test_ctx);
507
if (terminate_timer == NULL) {
508
fail("Error calling tevent_add_timer");
512
ret = test_loop(test_ctx);
513
check_leaks_pop(test_ctx);
514
fail_unless(ret == EOK);
517
talloc_zfree(test_ctx);
521
Suite *create_resolv_suite(void)
523
Suite *s = suite_create("resolv");
525
TCase *tc_resolv = tcase_create("RESOLV Tests");
527
tcase_add_checked_fixture(tc_resolv, leak_check_setup, leak_check_teardown);
528
/* Do some testing */
529
tcase_add_test(tc_resolv, test_copy_hostent);
530
tcase_add_test(tc_resolv, test_resolv_localhost);
531
tcase_add_test(tc_resolv, test_resolv_negative);
533
tcase_add_test(tc_resolv, test_resolv_internet);
534
if (txt_host != NULL) {
535
tcase_add_test(tc_resolv, test_resolv_internet_txt);
537
if (srv_host != NULL) {
538
tcase_add_test(tc_resolv, test_resolv_internet_srv);
541
tcase_add_test(tc_resolv, test_resolv_free_context);
542
tcase_add_test(tc_resolv, test_resolv_free_req);
544
/* Add all test cases to the test suite */
545
suite_add_tcase(s, tc_resolv);
550
int main(int argc, const char *argv[])
559
struct poptOption long_options[] = {
561
{ "debug-level", 'd', POPT_ARG_INT, &debug, 0, "Set debug level", NULL },
562
{ "use-net-test", 'n', POPT_ARG_NONE, 0, 'n', "Run tests that need an active internet connection", NULL },
563
{ "txt-host", 't', POPT_ARG_STRING, 0, 't', "Specify the host used for TXT record testing", NULL },
564
{ "srv-host", 's', POPT_ARG_STRING, 0, 's', "Specify the host used for SRV record testing", NULL },
568
pc = poptGetContext(argv[0], argc, argv, long_options, 0);
569
while((opt = poptGetNextOpt(pc)) != -1) {
575
txt_host = poptGetOptArg(pc);
578
srv_host = poptGetOptArg(pc);
581
fprintf(stderr, "\nInvalid option %s: %s\n\n",
582
poptBadOption(pc, 0), poptStrerror(opt));
583
poptPrintUsage(pc, stderr, 0);
590
resolv_suite = create_resolv_suite();
591
sr = srunner_create(resolv_suite);
592
/* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
593
srunner_run_all(sr, CK_ENV);
594
failure_count = srunner_ntests_failed(sr);
596
return (failure_count==0 ? EXIT_SUCCESS : EXIT_FAILURE);