Annotation of embedaddon/curl/tests/unit/unit1609.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: #include "curlcheck.h"
                     23: 
                     24: #include "urldata.h"
                     25: #include "connect.h"
                     26: #include "share.h"
                     27: 
                     28: #include "memdebug.h" /* LAST include file */
                     29: 
                     30: static void unit_stop(void)
                     31: {
                     32:   curl_global_cleanup();
                     33: }
                     34: 
                     35: static CURLcode unit_setup(void)
                     36: {
                     37:   int res = CURLE_OK;
                     38: 
                     39:   global_init(CURL_GLOBAL_ALL);
                     40: 
                     41:   return res;
                     42: }
                     43: 
                     44: struct testcase {
                     45:   /* host:port:address[,address]... */
                     46:   const char *optval;
                     47: 
                     48:   /* lowercase host and port to retrieve the addresses from hostcache */
                     49:   const char *host;
                     50:   int port;
                     51: 
                     52:   /* 0 to 9 addresses expected from hostcache */
                     53:   const char *address[10];
                     54: };
                     55: 
                     56: 
                     57: /* CURLOPT_RESOLVE address parsing test - to test the following defect fix:
                     58: 
                     59:  1) if there is already existing host:port pair in the DNS cache and
                     60:  we call CURLOPT_RESOLVE, it should also replace addresses.
                     61:  for example, if there is "test.com:80" with address "1.1.1.1"
                     62:  and we called CURLOPT_RESOLVE with address "2.2.2.2", then DNS entry needs to
                     63:  reflect that.
                     64: 
                     65:  2) when cached address is already there and close to expire, then by the
                     66:  time request is made, it can get expired.  This happens because, when
                     67:  we set address using CURLOPT_RESOLVE,
                     68:  it usually marks as permanent (by setting timestamp to zero). However,
                     69:  if address already exists
                     70: in the cache, then it does not mark it, but just leaves it as it is.
                     71:  So we fixing this by timestamp to zero if address already exists too.
                     72: 
                     73: Test:
                     74: 
                     75:  - insert new entry
                     76:  - verify that timestamp is not zero
                     77:  - call set options with CURLOPT_RESOLVE
                     78:  - then, call Curl_loadhostpairs
                     79: 
                     80:  expected result: cached address has zero timestamp.
                     81: 
                     82:  - call set options with CURLOPT_RESOLVE with same host:port pair,
                     83:    different address.
                     84:  - then, call Curl_loadhostpairs
                     85: 
                     86:  expected result: cached address has zero timestamp and new address
                     87: */
                     88: 
                     89: static const struct testcase tests[] = {
                     90:   /* spaces aren't allowed, for now */
                     91:   { "test.com:80:127.0.0.1",
                     92:     "test.com", 80, { "127.0.0.1", }
                     93:   },
                     94:   { "test.com:80:127.0.0.2",
                     95:     "test.com", 80, { "127.0.0.2", }
                     96:   },
                     97: };
                     98: 
                     99: UNITTEST_START
                    100: {
                    101:   int i;
                    102:   int testnum = sizeof(tests) / sizeof(struct testcase);
                    103:   struct Curl_multi *multi = NULL;
                    104:   struct Curl_easy *easy = NULL;
                    105:   struct curl_slist *list = NULL;
                    106: 
                    107: /* important: we setup cache outside of the loop
                    108:   and also clean cache after the loop. In contrast,for example,
                    109:   test 1607 sets up and cleans cache on each iteration. */
                    110: 
                    111:   for(i = 0; i < testnum; ++i) {
                    112:     int j;
                    113:     int addressnum = sizeof (tests[i].address) / sizeof (*tests[i].address);
                    114:     struct Curl_addrinfo *addr;
                    115:     struct Curl_dns_entry *dns;
                    116:     void *entry_id;
                    117:     bool problem = false;
                    118:     easy = curl_easy_init();
                    119:     if(!easy) {
                    120:       curl_global_cleanup();
                    121:       return CURLE_OUT_OF_MEMORY;
                    122:     }
                    123:     /* create a multi handle and add the easy handle to it so that the
                    124:        hostcache is setup */
                    125:     multi = curl_multi_init();
                    126:     if(!multi)
                    127:       goto error;
                    128:     curl_multi_add_handle(multi, easy);
                    129: 
                    130:     list = curl_slist_append(NULL, tests[i].optval);
                    131:     if(!list)
                    132:       goto error;
                    133: 
                    134:     curl_easy_setopt(easy, CURLOPT_RESOLVE, list);
                    135: 
                    136:     if(Curl_loadhostpairs(easy))
                    137:       goto error;
                    138: 
                    139:     entry_id = (void *)aprintf("%s:%d", tests[i].host, tests[i].port);
                    140:     if(!entry_id)
                    141:       goto error;
                    142: 
                    143:     dns = Curl_hash_pick(easy->dns.hostcache, entry_id, strlen(entry_id) + 1);
                    144:     free(entry_id);
                    145:     entry_id = NULL;
                    146: 
                    147:     addr = dns ? dns->addr : NULL;
                    148: 
                    149:     for(j = 0; j < addressnum; ++j) {
                    150:       long port = 0;
                    151:       char ipaddress[MAX_IPADR_LEN] = {0};
                    152: 
                    153:       if(!addr && !tests[i].address[j])
                    154:         break;
                    155: 
                    156:       if(addr && !Curl_addr2string(addr->ai_addr, addr->ai_addrlen,
                    157:                                    ipaddress, &port)) {
                    158:         fprintf(stderr, "%s:%d tests[%d] failed. Curl_addr2string failed.\n",
                    159:                 __FILE__, __LINE__, i);
                    160:         problem = true;
                    161:         break;
                    162:       }
                    163: 
                    164:       if(addr && !tests[i].address[j]) {
                    165:         fprintf(stderr, "%s:%d tests[%d] failed. the retrieved addr "
                    166:                 "is %s but tests[%d].address[%d] is NULL.\n",
                    167:                 __FILE__, __LINE__, i, ipaddress, i, j);
                    168:         problem = true;
                    169:         break;
                    170:       }
                    171: 
                    172:       if(!addr && tests[i].address[j]) {
                    173:         fprintf(stderr, "%s:%d tests[%d] failed. the retrieved addr "
                    174:                 "is NULL but tests[%d].address[%d] is %s.\n",
                    175:                 __FILE__, __LINE__, i, i, j, tests[i].address[j]);
                    176:         problem = true;
                    177:         break;
                    178:       }
                    179: 
                    180:       if(!curl_strequal(ipaddress, tests[i].address[j])) {
                    181:         fprintf(stderr, "%s:%d tests[%d] failed. the retrieved addr "
                    182:                 "%s is not equal to tests[%d].address[%d] %s.\n",
                    183:                 __FILE__, __LINE__, i, ipaddress, i, j, tests[i].address[j]);
                    184:         problem = true;
                    185:         break;
                    186:       }
                    187: 
                    188:       if(port != tests[i].port) {
                    189:         fprintf(stderr, "%s:%d tests[%d] failed. the retrieved port "
                    190:                 "for tests[%d].address[%d] is %ld but tests[%d].port is %d.\n",
                    191:                 __FILE__, __LINE__, i, i, j, port, i, tests[i].port);
                    192:         problem = true;
                    193:         break;
                    194:       }
                    195: 
                    196:       addr = addr->ai_next;
                    197:     }
                    198: 
                    199:     curl_easy_cleanup(easy);
                    200:     easy = NULL;
                    201:     Curl_hash_destroy(&multi->hostcache);
                    202:     curl_multi_cleanup(multi);
                    203:     multi = NULL;
                    204:     curl_slist_free_all(list);
                    205:     list = NULL;
                    206: 
                    207:     if(problem) {
                    208:       unitfail++;
                    209:       continue;
                    210:     }
                    211:   }
                    212:   goto unit_test_abort;
                    213:   error:
                    214:   curl_easy_cleanup(easy);
                    215:   curl_multi_cleanup(multi);
                    216:   curl_slist_free_all(list);
                    217: }
                    218: UNITTEST_STOP

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>