Return to unit1609.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / tests / unit |
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