LCOV - code coverage report
Current view: top level - tests - resolv-tests.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 315 539 58.4 %
Date: 2015-10-19 Functions: 16 26 61.5 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    Async resolver tests
       5             : 
       6             :    Authors:
       7             :         Martin Nagy <mnagy@redhat.com>
       8             :         Jakub Hrozek <jhrozek@redhat.com>
       9             : 
      10             :    Copyright (C) Red Hat, Inc 2009
      11             : 
      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.
      16             : 
      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.
      21             : 
      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/>.
      24             : */
      25             : 
      26             : #include <stdlib.h>
      27             : #include <check.h>
      28             : #include <string.h>
      29             : #include <talloc.h>
      30             : #include <tevent.h>
      31             : #include <popt.h>
      32             : #include <arpa/inet.h>
      33             : 
      34             : #include "tests/common.h"
      35             : #include "util/util.h"
      36             : #include "tests/common_check.h"
      37             : 
      38             : /* Interface under test */
      39             : #include "resolv/async_resolv.h"
      40             : 
      41             : #define RESOLV_DEFAULT_TIMEOUT 6
      42             : 
      43             : static int use_net_test;
      44             : static char *txt_host;
      45             : static char *srv_host;
      46             : 
      47             : struct resolv_test_ctx {
      48             :     struct tevent_context *ev;
      49             :     struct resolv_ctx *resolv;
      50             : 
      51             :     enum {
      52             :         TESTING_HOSTNAME,
      53             :         TESTING_TXT,
      54             :         TESTING_SRV,
      55             :     } tested_function;
      56             : 
      57             :     int error;
      58             :     bool done;
      59             : };
      60             : 
      61           5 : static int setup_resolv_test(int timeout, struct resolv_test_ctx **ctx)
      62             : {
      63             :     struct resolv_test_ctx *test_ctx;
      64             :     int ret;
      65             : 
      66           5 :     test_ctx = talloc_zero(global_talloc_context, struct resolv_test_ctx);
      67           5 :     if (test_ctx == NULL) {
      68           0 :         fail("Could not allocate memory for test context");
      69             :         return ENOMEM;
      70             :     }
      71             : 
      72           5 :     test_ctx->ev = tevent_context_init(test_ctx);
      73           5 :     if (test_ctx->ev == NULL) {
      74           0 :         fail("Could not init tevent context");
      75             :         talloc_free(test_ctx);
      76             :         return EFAULT;
      77             :     }
      78             : 
      79           5 :     ret = resolv_init(test_ctx, test_ctx->ev, timeout, &test_ctx->resolv);
      80           5 :     if (ret != EOK) {
      81           0 :         fail("Could not init resolv context");
      82             :         talloc_free(test_ctx);
      83             :         return ret;
      84             :     }
      85             : 
      86           5 :     *ctx = test_ctx;
      87           5 :     return EOK;
      88             : }
      89             : 
      90           3 : static int test_loop(struct resolv_test_ctx *data)
      91             : {
      92          19 :     while (!data->done)
      93          13 :         tevent_loop_once(data->ev);
      94             : 
      95           3 :     return data->error;
      96             : }
      97             : 
      98             : struct resolv_hostent *
      99           2 : test_create_rhostent(TALLOC_CTX *mem_ctx,
     100             :                      const char *hostname, const char *address)
     101             : {
     102             :     struct resolv_hostent *rhostent;
     103             :     int ret;
     104             :     int family;
     105             : 
     106           2 :     rhostent = talloc_zero(mem_ctx, struct resolv_hostent);
     107           2 :     if (!rhostent) {
     108           0 :         return NULL;
     109             :     }
     110             : 
     111           2 :     rhostent->name = talloc_strdup(rhostent, hostname);
     112           2 :     rhostent->addr_list = talloc_array(rhostent, struct resolv_addr *, 2);
     113           4 :     if (!rhostent->name ||
     114           2 :         !rhostent->addr_list) {
     115             :         goto fail;
     116             :     }
     117             : 
     118           2 :     rhostent->addr_list[0] = talloc_zero(rhostent->addr_list,
     119             :                                          struct resolv_addr);
     120           2 :     if (!rhostent->addr_list[0]) {
     121           0 :         goto fail;
     122             :     }
     123           2 :     rhostent->addr_list[0]->ipaddr = talloc_array(rhostent->addr_list[0],
     124             :                                                   uint8_t,
     125             :                                                   sizeof(struct in6_addr));
     126           2 :     if (!rhostent->addr_list[0]->ipaddr) {
     127           0 :         goto fail;
     128             :     }
     129             : 
     130           2 :     family = AF_INET;
     131           2 :     ret = inet_pton(family, address,
     132           2 :                     rhostent->addr_list[0]->ipaddr);
     133           2 :     if (ret != 1) {
     134           1 :         family = AF_INET6;
     135           1 :         ret = inet_pton(family, address,
     136           1 :                         rhostent->addr_list[0]->ipaddr);
     137           1 :         if (ret != 1) {
     138           0 :             goto fail;
     139             :         }
     140             :     }
     141             : 
     142           2 :     rhostent->addr_list[0]->ttl = RESOLV_DEFAULT_TTL;
     143           2 :     rhostent->addr_list[1] = NULL;
     144           2 :     rhostent->family = family;
     145           2 :     rhostent->aliases = NULL;
     146             : 
     147           2 :     return rhostent;
     148             : 
     149             : fail:
     150           0 :     talloc_free(rhostent);
     151           0 :     return NULL;
     152             : }
     153             : 
     154           1 : START_TEST(test_copy_hostent)
     155             : {
     156             :     void *ctx;
     157             :     struct resolv_hostent *rhe;
     158             : 
     159           1 :     char name[] = "foo.example.com";
     160           1 :     char alias_1[] = "bar.example.com";
     161           1 :     char alias_2[] = "baz.example.com";
     162           1 :     char *aliases[] = { alias_1, alias_2, NULL };
     163           1 :     struct in_addr addr_1 = { 1234 };
     164           1 :     struct in_addr addr_2 = { 5678 };
     165           1 :     int ttl_1 = 12;
     166           1 :     int ttl_2 = 34;
     167           1 :     char *addr_list[] = { (char *) &addr_2, (char *) &addr_1, NULL };
     168           1 :     struct hostent he = {
     169             :             name, aliases, AF_INET,
     170             :             sizeof(addr_1), addr_list
     171             :     };
     172           1 :     struct ares_addrttl attl[] = { { addr_1, ttl_1 }, { addr_2, ttl_2 } };
     173             : 
     174           1 :     ctx = talloc_new(global_talloc_context);
     175           1 :     fail_if(ctx == NULL);
     176             : 
     177           1 :     ck_leaks_push(ctx);
     178             : 
     179           1 :     rhe = resolv_copy_hostent_ares(ctx, &he, AF_INET, &attl, 2);
     180             : 
     181           1 :     fail_if(rhe == NULL);
     182           1 :     fail_if(strcmp(rhe->name, name));
     183           1 :     fail_if(strcmp(rhe->aliases[0], alias_1));
     184           1 :     fail_if(strcmp(rhe->aliases[1], alias_2));
     185           1 :     fail_if(rhe->aliases[2] != NULL);
     186           1 :     fail_if(rhe->family != AF_INET);
     187           1 :     fail_if(memcmp(rhe->addr_list[0]->ipaddr, &addr_1, sizeof(addr_1)));
     188           1 :     fail_if(rhe->addr_list[0]->ttl != ttl_1);
     189           1 :     fail_if(memcmp(rhe->addr_list[1]->ipaddr, &addr_2, sizeof(addr_2)));
     190           1 :     fail_if(rhe->addr_list[1]->ttl != ttl_2);
     191           1 :     fail_if(rhe->addr_list[2] != NULL);
     192             : 
     193           1 :     talloc_zfree(rhe);
     194             : 
     195           1 :     rhe = resolv_copy_hostent(ctx, &he);
     196           1 :     fail_if(rhe == NULL);
     197           1 :     fail_if(strcmp(rhe->name, name));
     198           1 :     fail_if(strcmp(rhe->aliases[0], alias_1));
     199           1 :     fail_if(strcmp(rhe->aliases[1], alias_2));
     200           1 :     fail_if(rhe->aliases[2] != NULL);
     201           1 :     fail_if(rhe->family != AF_INET);
     202           1 :     fail_if(memcmp(rhe->addr_list[0]->ipaddr, &addr_2, sizeof(addr_1)));
     203           1 :     fail_if(rhe->addr_list[0]->ttl != RESOLV_DEFAULT_TTL);
     204           1 :     fail_if(memcmp(rhe->addr_list[1]->ipaddr, &addr_1, sizeof(addr_2)));
     205           1 :     fail_if(rhe->addr_list[1]->ttl != RESOLV_DEFAULT_TTL);
     206           1 :     fail_if(rhe->addr_list[2] != NULL);
     207             : 
     208           1 :     talloc_free(rhe);
     209             : 
     210           1 :     ck_leaks_pop(ctx);
     211             : }
     212           1 : END_TEST
     213             : 
     214           1 : START_TEST(test_address_to_string)
     215             : {
     216             :     void *ctx;
     217             :     struct resolv_hostent *rhe;
     218             :     char *str_addr;
     219             :     char *ptr_addr;
     220             : 
     221           1 :     ctx = talloc_new(global_talloc_context);
     222           1 :     fail_if(ctx == NULL);
     223           1 :     ck_leaks_push(ctx);
     224             : 
     225           1 :     rhe = test_create_rhostent(ctx, "www.example.com", "1.2.3.4");
     226           1 :     fail_if(rhe == NULL);
     227             : 
     228           1 :     str_addr = resolv_get_string_address_index(ctx, rhe, 0);
     229           1 :     fail_if(str_addr == NULL);
     230           1 :     fail_unless(strcmp(str_addr, "1.2.3.4") == 0, "Unexpected address\n");
     231           1 :     talloc_free(str_addr);
     232             : 
     233           1 :     ptr_addr = resolv_get_string_ptr_address(ctx, rhe->family,
     234           1 :                                              rhe->addr_list[0]->ipaddr);
     235           1 :     fail_if(ptr_addr == NULL);
     236           1 :     fail_unless(strcmp(ptr_addr, "4.3.2.1.in-addr.arpa.") == 0, "Unexpected PTR address\n");
     237           1 :     talloc_free(ptr_addr);
     238             : 
     239           1 :     talloc_free(rhe);
     240             : 
     241           1 :     rhe = test_create_rhostent(ctx, "www6.example.com", "2607:f8b0:400c:c03::6a");
     242           1 :     fail_if(rhe == NULL);
     243             : 
     244           1 :     str_addr = resolv_get_string_address_index(ctx, rhe, 0);
     245           1 :     fail_if(str_addr == NULL);
     246           1 :     fail_unless(strcmp(str_addr, "2607:f8b0:400c:c03::6a") == 0, "Unexpected address\n");
     247           1 :     talloc_free(str_addr);
     248             : 
     249           1 :     ptr_addr = resolv_get_string_ptr_address(ctx, rhe->family,
     250           1 :                                              rhe->addr_list[0]->ipaddr);
     251           1 :     fail_if(ptr_addr == NULL);
     252           1 :     fail_unless(strcmp(ptr_addr,
     253             :                        "a.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.3.0.c.0.c.0.0.4.0.b.8.f.7.0.6.2.ip6.arpa.") == 0, "Unexpected PTR address\n");
     254           1 :     talloc_free(ptr_addr);
     255             : 
     256           1 :     talloc_free(rhe);
     257           1 :     ck_leaks_pop(ctx);
     258             : }
     259           1 : END_TEST
     260             : 
     261           1 : static void test_ip_addr(struct tevent_req *req)
     262             : {
     263             :     int recv_status;
     264             :     int status;
     265             :     struct resolv_hostent *rhostent;
     266             :     int i;
     267           1 :     struct resolv_test_ctx *test_ctx = tevent_req_callback_data(req,
     268             :                                                                 struct resolv_test_ctx);
     269             : 
     270           1 :     test_ctx->done = true;
     271             : 
     272           1 :     recv_status = resolv_gethostbyname_recv(req, test_ctx,
     273             :                                             &status, NULL, &rhostent);
     274           1 :     talloc_zfree(req);
     275           1 :     if (recv_status != EOK) {
     276           0 :         DEBUG(SSSDBG_OP_FAILURE,
     277             :               "resolv_gethostbyname_recv failed: %d\n", recv_status);
     278           0 :         test_ctx->error = recv_status;
     279           0 :         return;
     280             :     }
     281           1 :     DEBUG(SSSDBG_TRACE_LIBS, "resolv_gethostbyname_recv status: %d\n", status);
     282             : 
     283           1 :     test_ctx->error = ENOENT;
     284           2 :     for (i = 0; rhostent->addr_list[i]; i++) {
     285             :         char addr_buf[256];
     286           1 :         inet_ntop(rhostent->family,
     287           1 :                   rhostent->addr_list[i]->ipaddr,
     288             :                   addr_buf, sizeof(addr_buf));
     289             : 
     290           1 :         if (strcmp(addr_buf, "127.0.0.1") == 0) {
     291           1 :             test_ctx->error = EOK;
     292             :         }
     293             :     }
     294           1 :     talloc_free(rhostent);
     295             : }
     296             : 
     297           1 : START_TEST(test_resolv_ip_addr)
     298             : {
     299             :     struct resolv_test_ctx *test_ctx;
     300           1 :     int ret = EOK;
     301             :     struct tevent_req *req;
     302           1 :     const char *hostname = "127.0.0.1";
     303             : 
     304           1 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     305           1 :     if (ret != EOK) {
     306           0 :         fail("Could not set up test");
     307             :         return;
     308             :     }
     309             : 
     310           1 :     ck_leaks_push(test_ctx);
     311           1 :     req = resolv_gethostbyname_send(test_ctx, test_ctx->ev,
     312           1 :                                     test_ctx->resolv, hostname, IPV4_ONLY,
     313             :                                     default_host_dbs);
     314           1 :     DEBUG(SSSDBG_TRACE_LIBS, "Sent resolv_gethostbyname\n");
     315           1 :     if (req == NULL) {
     316           0 :         ret = ENOMEM;
     317             :     }
     318             : 
     319           1 :     if (ret == EOK) {
     320           1 :         tevent_req_set_callback(req, test_ip_addr, test_ctx);
     321           1 :         ret = test_loop(test_ctx);
     322             :     }
     323             : 
     324           1 :     ck_leaks_pop(test_ctx);
     325           1 :     fail_unless(ret == EOK);
     326             : 
     327           1 :     talloc_zfree(test_ctx);
     328             : }
     329           1 : END_TEST
     330             : 
     331           0 : static void test_localhost(struct tevent_req *req)
     332             : {
     333             :     int recv_status;
     334             :     int status;
     335             :     struct resolv_hostent *rhostent;
     336             :     int i;
     337           0 :     struct resolv_test_ctx *test_ctx = tevent_req_callback_data(req,
     338             :                                                                 struct resolv_test_ctx);
     339             : 
     340           0 :     test_ctx->done = true;
     341             : 
     342           0 :     recv_status = resolv_gethostbyname_recv(req, test_ctx,
     343             :                                             &status, NULL, &rhostent);
     344           0 :     talloc_zfree(req);
     345           0 :     if (recv_status != EOK) {
     346           0 :         DEBUG(SSSDBG_OP_FAILURE,
     347             :               "resolv_gethostbyname_recv failed: %d\n", recv_status);
     348           0 :         test_ctx->error = recv_status;
     349           0 :         return;
     350             :     }
     351           0 :     DEBUG(SSSDBG_TRACE_LIBS, "resolv_gethostbyname_recv status: %d\n", status);
     352             : 
     353           0 :     test_ctx->error = ENOENT;
     354           0 :     for (i = 0; rhostent->addr_list[i]; i++) {
     355             :         char addr_buf[256];
     356           0 :         inet_ntop(rhostent->family, rhostent->addr_list[i]->ipaddr,
     357             :                   addr_buf, sizeof(addr_buf));
     358             : 
     359             :         /* test that localhost resolves to 127.0.0.1 or ::1 */
     360           0 :         if (strcmp(addr_buf, "127.0.0.1") == 0 || strcmp(addr_buf, "::1") == 0) {
     361           0 :             test_ctx->error = EOK;
     362             :         }
     363             :     }
     364           0 :     talloc_free(rhostent);
     365             : }
     366             : 
     367           0 : START_TEST(test_resolv_localhost)
     368             : {
     369             :     struct resolv_test_ctx *test_ctx;
     370           0 :     int ret = EOK;
     371             :     struct tevent_req *req;
     372           0 :     const char *hostname = "localhost.localdomain";
     373             : 
     374           0 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     375           0 :     if (ret != EOK) {
     376           0 :         fail("Could not set up test");
     377             :         return;
     378             :     }
     379             : 
     380           0 :     ck_leaks_push(test_ctx);
     381           0 :     req = resolv_gethostbyname_send(test_ctx, test_ctx->ev,
     382           0 :                                     test_ctx->resolv, hostname, IPV4_FIRST,
     383             :                                     default_host_dbs);
     384           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Sent resolv_gethostbyname\n");
     385           0 :     if (req == NULL) {
     386           0 :         ret = ENOMEM;
     387             :     }
     388             : 
     389           0 :     if (ret == EOK) {
     390           0 :         tevent_req_set_callback(req, test_localhost, test_ctx);
     391           0 :         ret = test_loop(test_ctx);
     392             :     }
     393             : 
     394           0 :     ck_leaks_pop(test_ctx);
     395           0 :     fail_unless(ret == EOK);
     396             : 
     397           0 :     talloc_zfree(test_ctx);
     398             : }
     399           0 : END_TEST
     400             : 
     401           0 : static void test_negative(struct tevent_req *req)
     402             : {
     403             :      int recv_status;
     404             :      int status;
     405             :      struct resolv_hostent *hostent;
     406             :      struct resolv_test_ctx *test_ctx;
     407             : 
     408           0 :      test_ctx = tevent_req_callback_data(req, struct resolv_test_ctx);
     409           0 :      test_ctx->done = true;
     410             : 
     411           0 :      recv_status = resolv_gethostbyname_recv(req, test_ctx,
     412             :                                              &status, NULL, &hostent);
     413           0 :      talloc_zfree(req);
     414           0 :      if (recv_status == EOK) {
     415           0 :          DEBUG(SSSDBG_TRACE_LIBS,
     416             :                "resolv_gethostbyname_recv succeeded in a negative test\n");
     417           0 :          return;
     418             :      }
     419             : 
     420           0 :      test_ctx->error = status;
     421           0 :      DEBUG(SSSDBG_OP_FAILURE,
     422             :            "resolv_gethostbyname_recv status: %d: %s\n", status, resolv_strerror(status));
     423             : }
     424             : 
     425           0 : START_TEST(test_resolv_negative)
     426             : {
     427           0 :     int ret = EOK;
     428             :     struct tevent_req *req;
     429           0 :     const char *hostname = "sssd.foo";
     430             :     struct resolv_test_ctx *test_ctx;
     431             : 
     432           0 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     433           0 :     if (ret != EOK) {
     434           0 :         fail("Could not set up test");
     435             :         return;
     436             :     }
     437             : 
     438           0 :     ck_leaks_push(test_ctx);
     439           0 :     req = resolv_gethostbyname_send(test_ctx, test_ctx->ev,
     440           0 :                                     test_ctx->resolv, hostname, IPV4_FIRST,
     441             :                                     default_host_dbs);
     442           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Sent resolv_gethostbyname\n");
     443           0 :     if (req == NULL) {
     444           0 :         ret = ENOMEM;
     445             :     }
     446             : 
     447           0 :     if (ret == EOK) {
     448           0 :         tevent_req_set_callback(req, test_negative, test_ctx);
     449           0 :         ret = test_loop(test_ctx);
     450             :     }
     451             : 
     452           0 :     ck_leaks_pop(test_ctx);
     453             : 
     454           0 :     fail_unless(ret != EOK);
     455           0 :     fail_unless(test_ctx->error == ARES_ENOTFOUND);
     456           0 :     talloc_zfree(test_ctx);
     457             : }
     458           0 : END_TEST
     459             : 
     460           0 : static void test_internet(struct tevent_req *req)
     461             : {
     462             :     int recv_status;
     463             :     int status;
     464             :     struct resolv_test_ctx *test_ctx;
     465             :     void *tmp_ctx;
     466           0 :     struct resolv_hostent *rhostent = NULL;
     467           0 :     struct ares_txt_reply *txt_replies = NULL, *txtptr;
     468           0 :     struct ares_srv_reply *srv_replies = NULL, *srvptr;
     469             :     int i;
     470             : 
     471           0 :     test_ctx = tevent_req_callback_data(req, struct resolv_test_ctx);
     472             : 
     473           0 :     test_ctx->done = true;
     474             : 
     475           0 :     tmp_ctx = talloc_new(test_ctx);
     476           0 :     ck_leaks_push(tmp_ctx);
     477             : 
     478           0 :     switch (test_ctx->tested_function) {
     479             :     case TESTING_HOSTNAME:
     480           0 :         recv_status = resolv_gethostbyname_recv(req, tmp_ctx,
     481             :                                                 &status, NULL, &rhostent);
     482           0 :         test_ctx->error = (rhostent->name == NULL) ? ENOENT : EOK;
     483           0 :         if (test_ctx->error == EOK) {
     484             :             char addr_buf[256];
     485           0 :             for (i=0; rhostent->addr_list[i]; i++) {
     486           0 :                 inet_ntop(rhostent->family,
     487           0 :                           rhostent->addr_list[i]->ipaddr,
     488             :                           addr_buf, sizeof(addr_buf));
     489           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Found address %s with TTL %d\n",
     490             :                           addr_buf, rhostent->addr_list[i]->ttl);
     491             :             }
     492             :         }
     493           0 :         break;
     494             :     case TESTING_TXT:
     495           0 :         recv_status = resolv_gettxt_recv(tmp_ctx, req, &status, NULL,
     496             :                                          &txt_replies);
     497           0 :         test_ctx->error = (txt_replies == NULL) ? ENOENT : EOK;
     498           0 :         for (txtptr = txt_replies; txtptr != NULL; txtptr = txtptr->next) {
     499           0 :             DEBUG(SSSDBG_OP_FAILURE, "TXT Record: %s\n", txtptr->txt);
     500             :         }
     501           0 :         break;
     502             :     case TESTING_SRV:
     503           0 :         recv_status = resolv_getsrv_recv(tmp_ctx, req, &status, NULL,
     504             :                                          &srv_replies, NULL);
     505           0 :         test_ctx->error = (srv_replies == NULL) ? ENOENT : EOK;
     506           0 :         for (srvptr = srv_replies; srvptr != NULL; srvptr = srvptr->next) {
     507           0 :             DEBUG(SSSDBG_OP_FAILURE,
     508             :                   "SRV Record: %d %d %d %s\n", srvptr->weight,
     509             :                       srvptr->priority, srvptr->port,
     510             :                       srvptr->host);
     511             :         }
     512           0 :         break;
     513             :     default:
     514           0 :         recv_status = EINVAL;
     515           0 :         break;
     516             :     }
     517           0 :     talloc_zfree(req);
     518           0 :     fail_if(recv_status != EOK, "The recv function failed: %d", recv_status);
     519           0 :     DEBUG(SSSDBG_TRACE_LIBS, "recv status: %d\n", status);
     520             : 
     521           0 :     if (rhostent != NULL) {
     522           0 :         talloc_free(rhostent);
     523           0 :     } else if (txt_replies != NULL) {
     524           0 :         talloc_free(txt_replies);
     525           0 :     } else if (srv_replies != NULL) {
     526           0 :         talloc_free(srv_replies);
     527             :     }
     528           0 :     ck_leaks_pop(tmp_ctx);
     529           0 : }
     530             : 
     531           0 : START_TEST(test_resolv_internet)
     532             : {
     533           0 :     int ret = EOK;
     534             :     struct tevent_req *req;
     535           0 :     const char *hostname = "redhat.com";
     536             :     struct resolv_test_ctx *test_ctx;
     537             : 
     538           0 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     539           0 :     if (ret != EOK) {
     540           0 :         fail("Could not set up test");
     541             :         return;
     542             :     }
     543           0 :     test_ctx->tested_function = TESTING_HOSTNAME;
     544             : 
     545           0 :     ck_leaks_push(test_ctx);
     546           0 :     req = resolv_gethostbyname_send(test_ctx, test_ctx->ev,
     547           0 :                                     test_ctx->resolv, hostname, IPV4_FIRST,
     548             :                                     default_host_dbs);
     549           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Sent resolv_gethostbyname\n");
     550           0 :     if (req == NULL) {
     551           0 :         ret = ENOMEM;
     552             :     }
     553             : 
     554           0 :     if (ret == EOK) {
     555           0 :         tevent_req_set_callback(req, test_internet, test_ctx);
     556           0 :         ret = test_loop(test_ctx);
     557             :     }
     558             : 
     559           0 :     fail_unless(ret == EOK);
     560           0 :     ck_leaks_pop(test_ctx);
     561           0 :     talloc_zfree(test_ctx);
     562             : }
     563           0 : END_TEST
     564             : 
     565           0 : START_TEST(test_resolv_internet_txt)
     566             : {
     567             :     int ret;
     568             :     struct tevent_req *req;
     569             :     struct resolv_test_ctx *test_ctx;
     570             : 
     571           0 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     572           0 :     fail_if(ret != EOK, "Could not set up test");
     573           0 :     test_ctx->tested_function = TESTING_TXT;
     574             : 
     575           0 :     ck_leaks_push(test_ctx);
     576             : 
     577           0 :     req = resolv_gettxt_send(test_ctx, test_ctx->ev, test_ctx->resolv, txt_host);
     578           0 :     fail_if(req == NULL, "Function resolv_gettxt_send failed");
     579             : 
     580           0 :     tevent_req_set_callback(req, test_internet, test_ctx);
     581           0 :     ret = test_loop(test_ctx);
     582           0 :     fail_unless(ret == EOK);
     583             : 
     584           0 :     ck_leaks_pop(test_ctx);
     585             : 
     586           0 :     talloc_zfree(test_ctx);
     587             : }
     588           0 : END_TEST
     589             : 
     590           0 : START_TEST(test_resolv_internet_srv)
     591             : {
     592             :     int ret;
     593             :     struct tevent_req *req;
     594             :     struct resolv_test_ctx *test_ctx;
     595             : 
     596           0 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     597           0 :     fail_if(ret != EOK, "Could not set up test");
     598           0 :     test_ctx->tested_function = TESTING_SRV;
     599             : 
     600           0 :     ck_leaks_push(test_ctx);
     601             : 
     602           0 :     req = resolv_getsrv_send(test_ctx, test_ctx->ev, test_ctx->resolv, srv_host);
     603           0 :     fail_if(req == NULL, "Function resolv_getsrv_send failed");
     604             : 
     605           0 :     tevent_req_set_callback(req, test_internet, test_ctx);
     606           0 :     ret = test_loop(test_ctx);
     607           0 :     fail_unless(ret == EOK);
     608             : 
     609           0 :     ck_leaks_pop(test_ctx);
     610             : 
     611           0 :     talloc_zfree(test_ctx);
     612             : }
     613           0 : END_TEST
     614             : 
     615           1 : static void resolv_free_context(struct tevent_context *ev,
     616             :                                 struct tevent_timer *te,
     617             :                                 struct timeval t, void *ptr)
     618             : {
     619           1 :     struct resolv_ctx *rctx = talloc_get_type(ptr, struct resolv_ctx);
     620           1 :     DEBUG(SSSDBG_TRACE_LIBS, "freeing the context\n");
     621             : 
     622           1 :     talloc_free(rctx);
     623           1 : }
     624             : 
     625           2 : static void resolv_free_done(struct tevent_context *ev,
     626             :                              struct tevent_timer *te,
     627             :                              struct timeval t, void *ptr)
     628             : {
     629           2 :     struct resolv_test_ctx *tctx = talloc_get_type(ptr, struct resolv_test_ctx);
     630           2 :     DEBUG(SSSDBG_TRACE_LIBS, "marking test as done\n");
     631             : 
     632           2 :     tctx->error = EOK;
     633           2 :     tctx->done = true;
     634           2 : }
     635             : 
     636           1 : START_TEST(test_resolv_free_context)
     637             : {
     638           1 :     int ret = EOK;
     639             :     struct tevent_req *req;
     640           1 :     const char *hostname = "redhat.com";
     641             :     struct resolv_test_ctx *test_ctx;
     642             :     struct tevent_timer *free_timer, *terminate_timer;
     643             :     struct timeval free_tv, terminate_tv;
     644             : 
     645           1 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     646           1 :     if (ret != EOK) {
     647           0 :         fail("Could not set up test");
     648             :         return;
     649             :     }
     650             : 
     651           1 :     req = resolv_gethostbyname_send(test_ctx, test_ctx->ev,
     652           1 :                                     test_ctx->resolv, hostname, IPV4_FIRST,
     653             :                                     default_host_dbs);
     654           1 :     DEBUG(SSSDBG_TRACE_LIBS, "Sent resolv_gethostbyname\n");
     655           1 :     if (req == NULL) {
     656           0 :         fail("Error calling resolv_gethostbyname_send");
     657             :         goto done;
     658             :     }
     659             : 
     660           1 :     gettimeofday(&free_tv, NULL);
     661           1 :     free_tv.tv_sec += 1;
     662           1 :     free_tv.tv_usec = 0;
     663           1 :     terminate_tv.tv_sec  = free_tv.tv_sec + 1;
     664           1 :     terminate_tv.tv_usec = 0;
     665             : 
     666           1 :     free_timer = tevent_add_timer(test_ctx->ev, test_ctx, free_tv, resolv_free_context, test_ctx->resolv);
     667           1 :     if (free_timer == NULL) {
     668           0 :         fail("Error calling tevent_add_timer");
     669             :         goto done;
     670             :     }
     671             : 
     672           1 :     terminate_timer = tevent_add_timer(test_ctx->ev, test_ctx, terminate_tv, resolv_free_done, test_ctx);
     673           1 :     if (terminate_timer == NULL) {
     674           0 :         fail("Error calling tevent_add_timer");
     675             :         goto done;
     676             :     }
     677             : 
     678           1 :     ret = test_loop(test_ctx);
     679           1 :     fail_unless(ret == EOK);
     680             : 
     681             : done:
     682           1 :     talloc_zfree(test_ctx);
     683             : }
     684           1 : END_TEST
     685             : 
     686           1 : static void resolv_free_req(struct tevent_context *ev,
     687             :                             struct tevent_timer *te,
     688             :                             struct timeval t, void *ptr)
     689             : {
     690           1 :     struct tevent_req *req = talloc_get_type(ptr, struct tevent_req);
     691           1 :     DEBUG(SSSDBG_TRACE_LIBS, "freeing the request\n");
     692             : 
     693           1 :     talloc_free(req);
     694           1 : }
     695             : 
     696           1 : START_TEST(test_resolv_sort_srv_reply)
     697             : {
     698             :     int ret;
     699           1 :     struct ares_srv_reply *replies = NULL;
     700           1 :     struct ares_srv_reply *r, *prev = NULL;
     701             :     struct resolv_test_ctx *test_ctx;
     702           1 :     int num_replies = 3;
     703             :     int i;
     704             : 
     705           1 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     706           1 :     if (ret != EOK) {
     707           0 :         fail("Could not set up test");
     708             :         return;
     709             :     }
     710             : 
     711           1 :     ck_leaks_push(test_ctx);
     712             : 
     713             :     /* prepare linked list with reversed values */
     714           4 :     for (i = 0; i<num_replies; i++) {
     715           3 :         r = talloc_zero(test_ctx, struct ares_srv_reply);
     716           3 :         fail_if(r == NULL);
     717           3 :         r->priority = num_replies-i;
     718           3 :         r->weight   = i;
     719             : 
     720           3 :         if (!replies) {
     721           1 :             replies = r;
     722           1 :             prev = r;
     723             :         } else {
     724           2 :             prev->next = r;
     725           2 :             prev = prev->next;
     726             :         }
     727             :     }
     728             : 
     729             :     /* do the sort */
     730           1 :     ret = resolv_sort_srv_reply(&replies);
     731           1 :     fail_if(ret != EOK);
     732             : 
     733             :     /* check if the list is sorted */
     734           1 :     prev = NULL;
     735           4 :     for (i = 1, r = replies; r; r=r->next, i++) {
     736           3 :         talloc_zfree(prev);
     737           3 :         prev = r;
     738           3 :         fail_unless(r->priority == i);
     739             :     }
     740           1 :     talloc_zfree(prev);
     741             : 
     742             :     /* check if the list is complete */
     743           1 :     fail_unless(i-1 == num_replies);
     744             : 
     745             :     /* test if the weighting algorithm runs..not much do
     746             :      * deterministically test here since it is based on
     747             :      * random weight-selection */
     748           1 :     replies = NULL;
     749           4 :     for (i = 0; i<num_replies; i++) {
     750           3 :         r = talloc_zero(test_ctx, struct ares_srv_reply);
     751           3 :         fail_if(r == NULL);
     752           3 :         r->priority = i % 2 + 1;
     753           3 :         r->weight   = i;
     754             : 
     755           3 :         if (!replies) {
     756           1 :             replies = r;
     757           1 :             prev = r;
     758             :         } else {
     759           2 :             prev->next = r;
     760           2 :             prev = prev->next;
     761             :         }
     762             :     }
     763             : 
     764             :     /* do the sort */
     765           1 :     ret = resolv_sort_srv_reply(&replies);
     766           1 :     fail_if(ret != EOK);
     767             : 
     768             :     /* clean up */
     769           1 :     prev = NULL;
     770           4 :     for (r = replies; r; r=r->next) {
     771           3 :         talloc_zfree(prev);
     772           3 :         prev = r;
     773             :     }
     774           1 :     talloc_zfree(prev);
     775             : 
     776             : 
     777             :     /* check for leaks */
     778           1 :     ck_leaks_pop(test_ctx);
     779           1 :     talloc_zfree(test_ctx);
     780             : }
     781           1 : END_TEST
     782             : 
     783           1 : START_TEST(test_resolv_sort_srv_reply_zero_weight)
     784             : {
     785             :     int ret;
     786           1 :     struct ares_srv_reply *replies = NULL;
     787           1 :     struct ares_srv_reply *r, *prev = NULL;
     788             :     struct resolv_test_ctx *test_ctx;
     789           1 :     int num_replies = 6;
     790             :     int i;
     791             : 
     792           1 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     793           1 :     if (ret != EOK) {
     794           0 :         fail("Could not set up test");
     795             :         return;
     796             :     }
     797             : 
     798           1 :     ck_leaks_push(test_ctx);
     799             : 
     800             :     /* prepare linked list */
     801           7 :     for (i = 0; i < num_replies; i++) {
     802           6 :         r = talloc_zero(test_ctx, struct ares_srv_reply);
     803           6 :         fail_if(r == NULL);
     804             : 
     805           6 :         r->priority = 20;
     806           6 :         r->priority = i <= 3 ? 10 : r->priority;
     807           6 :         r->priority = i <= 1 ? 0 : r->priority;
     808           6 :         r->weight   = 0;
     809             : 
     810           6 :         if (replies == NULL) {
     811           1 :             replies = r;
     812           1 :             prev = r;
     813             :         } else {
     814           5 :             prev->next = r;
     815           5 :             prev = prev->next;
     816             :         }
     817             :     }
     818             : 
     819             :     /* do the sort */
     820           1 :     ret = resolv_sort_srv_reply(&replies);
     821           1 :     fail_if(ret != EOK);
     822             : 
     823             :     /* check if the list contains all values and is sorted */
     824           7 :     for (i = 0, r = replies; r != NULL; r = r->next, i++) {
     825           6 :         if (r->next != NULL) {
     826           5 :             fail_unless(r->priority <= r->next->priority);
     827             :         }
     828             :     }
     829           1 :     fail_unless(i == num_replies);
     830             : 
     831             :     /* clean up */
     832           1 :     prev = NULL;
     833           7 :     for (r = replies; r != NULL; r=r->next) {
     834           6 :         talloc_zfree(prev);
     835           6 :         prev = r;
     836             :     }
     837           1 :     talloc_zfree(prev);
     838             : 
     839             : 
     840             :     /* check for leaks */
     841           1 :     ck_leaks_pop(test_ctx);
     842           1 :     talloc_zfree(test_ctx);
     843             : }
     844           1 : END_TEST
     845             : 
     846           1 : START_TEST(test_resolv_free_req)
     847             : {
     848           1 :     int ret = EOK;
     849             :     struct tevent_req *req;
     850           1 :     const char *hostname = "redhat.com";
     851             :     struct resolv_test_ctx *test_ctx;
     852             :     struct tevent_timer *free_timer, *terminate_timer;
     853             :     struct timeval free_tv, terminate_tv;
     854             : 
     855           1 :     ret = setup_resolv_test(RESOLV_DEFAULT_TIMEOUT, &test_ctx);
     856           1 :     if (ret != EOK) {
     857           0 :         fail("Could not set up test");
     858             :         return;
     859             :     }
     860             : 
     861           1 :     ck_leaks_push(test_ctx);
     862           1 :     req = resolv_gethostbyname_send(test_ctx, test_ctx->ev,
     863           1 :                                     test_ctx->resolv, hostname, IPV4_FIRST,
     864             :                                     default_host_dbs);
     865           1 :     DEBUG(SSSDBG_TRACE_LIBS, "Sent resolv_gethostbyname\n");
     866           1 :     if (req == NULL) {
     867           0 :         fail("Error calling resolv_gethostbyname_send");
     868             :         goto done;
     869             :     }
     870             : 
     871           1 :     gettimeofday(&free_tv, NULL);
     872           1 :     free_tv.tv_sec += 1;
     873           1 :     free_tv.tv_usec = 0;
     874             :     /* Give enought time for c-ares request to terminate */
     875           1 :     terminate_tv.tv_sec  = free_tv.tv_sec + 6;
     876           1 :     terminate_tv.tv_usec = 0;
     877             : 
     878           1 :     free_timer = tevent_add_timer(test_ctx->ev, test_ctx, free_tv, resolv_free_req, req);
     879           1 :     if (free_timer == NULL) {
     880           0 :         fail("Error calling tevent_add_timer");
     881             :         goto done;
     882             :     }
     883             : 
     884           1 :     terminate_timer = tevent_add_timer(test_ctx->ev, test_ctx, terminate_tv, resolv_free_done, test_ctx);
     885           1 :     if (terminate_timer == NULL) {
     886           0 :         fail("Error calling tevent_add_timer");
     887             :         goto done;
     888             :     }
     889             : 
     890           1 :     ret = test_loop(test_ctx);
     891           1 :     ck_leaks_pop(test_ctx);
     892           1 :     fail_unless(ret == EOK);
     893             : 
     894             : done:
     895           1 :     talloc_zfree(test_ctx);
     896             : }
     897           1 : END_TEST
     898             : 
     899           0 : static void test_timeout(struct tevent_req *req)
     900             : {
     901             :     int recv_status;
     902             :     int status;
     903             :     struct resolv_test_ctx *test_ctx;
     904             :     TALLOC_CTX *tmp_ctx;
     905           0 :     struct resolv_hostent *rhostent = NULL;
     906             : 
     907           0 :     test_ctx = tevent_req_callback_data(req, struct resolv_test_ctx);
     908             : 
     909           0 :     test_ctx->done = true;
     910             : 
     911           0 :     tmp_ctx = talloc_new(test_ctx);
     912           0 :     ck_leaks_push(tmp_ctx);
     913             : 
     914           0 :     fail_unless(test_ctx->tested_function == TESTING_HOSTNAME);
     915           0 :     recv_status = resolv_gethostbyname_recv(req, tmp_ctx,
     916             :                                             &status, NULL, &rhostent);
     917           0 :     talloc_zfree(req);
     918           0 :     fail_unless(recv_status == ETIMEDOUT);
     919           0 :     fail_unless(status == ARES_ETIMEOUT);
     920           0 :     ck_leaks_pop(tmp_ctx);
     921           0 :     talloc_free(tmp_ctx);
     922           0 : }
     923             : 
     924           0 : START_TEST(test_resolv_timeout)
     925             : {
     926             :     struct resolv_test_ctx *test_ctx;
     927             :     errno_t ret;
     928             :     struct tevent_req *req;
     929           0 :     const char *hostname = "redhat.com";
     930             : 
     931           0 :     ret = setup_resolv_test(0, &test_ctx);
     932           0 :     if (ret != EOK) {
     933           0 :         fail("Could not set up test");
     934             :         return;
     935             :     }
     936             : 
     937           0 :     test_ctx->tested_function = TESTING_HOSTNAME;
     938             : 
     939           0 :     req = resolv_gethostbyname_send(test_ctx, test_ctx->ev,
     940           0 :                                     test_ctx->resolv, hostname, IPV4_FIRST,
     941             :                                     default_host_dbs);
     942           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Sent resolv_gethostbyname\n");
     943           0 :     if (req == NULL) {
     944           0 :         ret = ENOMEM;
     945             :     }
     946             : 
     947           0 :     if (ret == EOK) {
     948           0 :         tevent_req_set_callback(req, test_timeout, test_ctx);
     949           0 :         ret = test_loop(test_ctx);
     950             :     }
     951             : 
     952           0 :     fail_unless(ret == EOK);
     953           0 :     talloc_zfree(test_ctx);
     954             : }
     955           0 : END_TEST
     956             : 
     957           1 : Suite *create_resolv_suite(void)
     958             : {
     959           1 :     Suite *s = suite_create("resolv");
     960             : 
     961           1 :     TCase *tc_resolv = tcase_create("RESOLV Tests");
     962           1 :     tcase_set_timeout(tc_resolv, 8);
     963             : 
     964           1 :     tcase_add_checked_fixture(tc_resolv, ck_leak_check_setup, ck_leak_check_teardown);
     965             :     /* Do some testing */
     966           1 :     tcase_add_test(tc_resolv, test_copy_hostent);
     967           1 :     tcase_add_test(tc_resolv, test_address_to_string);
     968           1 :     tcase_add_test(tc_resolv, test_resolv_ip_addr);
     969           1 :     tcase_add_test(tc_resolv, test_resolv_sort_srv_reply);
     970           1 :     tcase_add_test(tc_resolv, test_resolv_sort_srv_reply_zero_weight);
     971           1 :     if (use_net_test) {
     972           0 :         tcase_add_test(tc_resolv, test_resolv_internet);
     973           0 :         tcase_add_test(tc_resolv, test_resolv_negative);
     974           0 :         tcase_add_test(tc_resolv, test_resolv_localhost);
     975           0 :         tcase_add_test(tc_resolv, test_resolv_timeout);
     976           0 :         if (txt_host != NULL) {
     977           0 :             tcase_add_test(tc_resolv, test_resolv_internet_txt);
     978             :         }
     979           0 :         if (srv_host != NULL) {
     980           0 :             tcase_add_test(tc_resolv, test_resolv_internet_srv);
     981             :         }
     982             :     }
     983           1 :     tcase_add_test(tc_resolv, test_resolv_free_context);
     984           1 :     tcase_add_test(tc_resolv, test_resolv_free_req);
     985             : 
     986             :     /* Add all test cases to the test suite */
     987           1 :     suite_add_tcase(s, tc_resolv);
     988             : 
     989           1 :     return s;
     990             : }
     991             : 
     992           1 : int main(int argc, const char *argv[])
     993             : {
     994             :     int opt;
     995             :     poptContext pc;
     996             :     int failure_count;
     997             :     Suite *resolv_suite;
     998             :     SRunner *sr;
     999           1 :     int debug = 0;
    1000             : 
    1001           1 :     struct poptOption long_options[] = {
    1002             :         POPT_AUTOHELP
    1003             :         { "debug-level", 'd', POPT_ARG_INT, &debug, 0, "Set debug level", NULL },
    1004             :         { "use-net-test", 'n', POPT_ARG_NONE, 0, 'n', "Run tests that need an active internet connection", NULL },
    1005             :         { "txt-host", 't', POPT_ARG_STRING, 0, 't', "Specify the host used for TXT record testing", NULL },
    1006             :         { "srv-host", 's', POPT_ARG_STRING, 0, 's', "Specify the host used for SRV record testing", NULL },
    1007             :         POPT_TABLEEND
    1008             :     };
    1009             : 
    1010             :     /* Set debug level to invalid value so we can deside if -d 0 was used. */
    1011           1 :     debug_level = SSSDBG_INVALID;
    1012             : 
    1013           1 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
    1014           1 :     while((opt = poptGetNextOpt(pc)) != -1) {
    1015           0 :         switch(opt) {
    1016             :         case 'n':
    1017           0 :             use_net_test = 1;
    1018           0 :             break;
    1019             :         case 't':
    1020           0 :             txt_host = poptGetOptArg(pc);
    1021           0 :             break;
    1022             :         case 's':
    1023           0 :             srv_host = poptGetOptArg(pc);
    1024           0 :             break;
    1025             :         default:
    1026           0 :             fprintf(stderr, "\nInvalid option %s: %s\n\n",
    1027             :                     poptBadOption(pc, 0), poptStrerror(opt));
    1028           0 :             poptPrintUsage(pc, stderr, 0);
    1029           0 :             return 1;
    1030             :         }
    1031             :     }
    1032           1 :     poptFreeContext(pc);
    1033             : 
    1034           1 :     DEBUG_CLI_INIT(debug);
    1035             : 
    1036           1 :     if (!use_net_test) {
    1037           1 :         printf("Network tests disabled. Rerun with the \"-n\" "
    1038             :                "option to run the full suite of tests\n");
    1039             :     }
    1040             : 
    1041           1 :     tests_set_cwd();
    1042             : 
    1043           1 :     resolv_suite = create_resolv_suite();
    1044           1 :     sr = srunner_create(resolv_suite);
    1045             :     /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
    1046           1 :     srunner_run_all(sr, CK_ENV);
    1047           1 :     failure_count = srunner_ntests_failed(sr);
    1048           1 :     srunner_free(sr);
    1049           1 :     return (failure_count==0 ? EXIT_SUCCESS : EXIT_FAILURE);
    1050             : }
    1051             : 

Generated by: LCOV version 1.10