1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 http://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 "test.h" 23 24#include <curl/mprintf.h> 25 26#include "memdebug.h" 27 28static const char *HOSTHEADER = "Host: www.host.foo.com"; 29static const char *JAR = "log/jar506"; 30#define THREADS 2 31 32/* struct containing data of a thread */ 33struct Tdata { 34 CURLSH *share; 35 char *url; 36}; 37 38struct userdata { 39 char *text; 40 int counter; 41}; 42 43/* lock callback */ 44static void my_lock(CURL *handle, curl_lock_data data, curl_lock_access laccess, 45 void *useptr ) 46{ 47 const char *what; 48 struct userdata *user = (struct userdata *)useptr; 49 50 (void)handle; 51 (void)laccess; 52 53 switch ( data ) { 54 case CURL_LOCK_DATA_SHARE: 55 what = "share"; 56 break; 57 case CURL_LOCK_DATA_DNS: 58 what = "dns"; 59 break; 60 case CURL_LOCK_DATA_COOKIE: 61 what = "cookie"; 62 break; 63 default: 64 fprintf(stderr, "lock: no such data: %d\n", (int)data); 65 return; 66 } 67 printf("lock: %-6s [%s]: %d\n", what, user->text, user->counter); 68 user->counter++; 69} 70 71/* unlock callback */ 72static void my_unlock(CURL *handle, curl_lock_data data, void *useptr ) 73{ 74 const char *what; 75 struct userdata *user = (struct userdata *)useptr; 76 (void)handle; 77 switch ( data ) { 78 case CURL_LOCK_DATA_SHARE: 79 what = "share"; 80 break; 81 case CURL_LOCK_DATA_DNS: 82 what = "dns"; 83 break; 84 case CURL_LOCK_DATA_COOKIE: 85 what = "cookie"; 86 break; 87 default: 88 fprintf(stderr, "unlock: no such data: %d\n", (int)data); 89 return; 90 } 91 printf("unlock: %-6s [%s]: %d\n", what, user->text, user->counter); 92 user->counter++; 93} 94 95 96/* build host entry */ 97static struct curl_slist *sethost(struct curl_slist *headers) 98{ 99 (void)headers; 100 return curl_slist_append(NULL, HOSTHEADER ); 101} 102 103 104/* the dummy thread function */ 105static void *fire(void *ptr) 106{ 107 CURLcode code; 108 struct curl_slist *headers; 109 struct Tdata *tdata = (struct Tdata*)ptr; 110 CURL *curl; 111 int i=0; 112 113 if ((curl = curl_easy_init()) == NULL) { 114 fprintf(stderr, "curl_easy_init() failed\n"); 115 return NULL; 116 } 117 118 headers = sethost(NULL); 119 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 120 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 121 curl_easy_setopt(curl, CURLOPT_URL, tdata->url); 122 printf( "CURLOPT_SHARE\n" ); 123 curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share); 124 125 printf( "PERFORM\n" ); 126 code = curl_easy_perform(curl); 127 if( code != CURLE_OK ) { 128 fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n", 129 tdata->url, i, (int)code); 130 } 131 132 printf( "CLEANUP\n" ); 133 curl_easy_cleanup(curl); 134 curl_slist_free_all(headers); 135 136 return NULL; 137} 138 139 140/* build request url */ 141static char *suburl(const char *base, int i) 142{ 143 return curl_maprintf("%s%.4d", base, i); 144} 145 146 147/* test function */ 148int test(char *URL) 149{ 150 int res; 151 CURLSHcode scode = CURLSHE_OK; 152 char *url; 153 struct Tdata tdata; 154 CURL *curl; 155 CURLSH *share; 156 struct curl_slist *headers; 157 int i; 158 struct userdata user; 159 160 user.text = (char *)"Pigs in space"; 161 user.counter = 0; 162 163 printf( "GLOBAL_INIT\n" ); 164 if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 165 fprintf(stderr, "curl_global_init() failed\n"); 166 return TEST_ERR_MAJOR_BAD; 167 } 168 169 /* prepare share */ 170 printf( "SHARE_INIT\n" ); 171 if ((share = curl_share_init()) == NULL) { 172 fprintf(stderr, "curl_share_init() failed\n"); 173 curl_global_cleanup(); 174 return TEST_ERR_MAJOR_BAD; 175 } 176 177 if ( CURLSHE_OK == scode ) { 178 printf( "CURLSHOPT_LOCKFUNC\n" ); 179 scode = curl_share_setopt( share, CURLSHOPT_LOCKFUNC, my_lock); 180 } 181 if ( CURLSHE_OK == scode ) { 182 printf( "CURLSHOPT_UNLOCKFUNC\n" ); 183 scode = curl_share_setopt( share, CURLSHOPT_UNLOCKFUNC, my_unlock); 184 } 185 if ( CURLSHE_OK == scode ) { 186 printf( "CURLSHOPT_USERDATA\n" ); 187 scode = curl_share_setopt( share, CURLSHOPT_USERDATA, &user); 188 } 189 if ( CURLSHE_OK == scode ) { 190 printf( "CURL_LOCK_DATA_COOKIE\n" ); 191 scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); 192 } 193 if ( CURLSHE_OK == scode ) { 194 printf( "CURL_LOCK_DATA_DNS\n" ); 195 scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); 196 } 197 198 if ( CURLSHE_OK != scode ) { 199 fprintf(stderr, "curl_share_setopt() failed\n"); 200 curl_share_cleanup(share); 201 curl_global_cleanup(); 202 return TEST_ERR_MAJOR_BAD; 203 } 204 205 206 res = 0; 207 208 /* start treads */ 209 for (i=1; i<=THREADS; i++ ) { 210 211 /* set thread data */ 212 tdata.url = suburl( URL, i ); /* must be curl_free()d */ 213 tdata.share = share; 214 215 /* simulate thread, direct call of "thread" function */ 216 printf( "*** run %d\n",i ); 217 fire( &tdata ); 218 219 curl_free( tdata.url ); 220 221 } 222 223 224 /* fetch a another one and save cookies */ 225 printf( "*** run %d\n", i ); 226 if ((curl = curl_easy_init()) == NULL) { 227 fprintf(stderr, "curl_easy_init() failed\n"); 228 curl_share_cleanup(share); 229 curl_global_cleanup(); 230 return TEST_ERR_MAJOR_BAD; 231 } 232 233 url = suburl( URL, i ); 234 headers = sethost( NULL ); 235 test_setopt( curl, CURLOPT_HTTPHEADER, headers ); 236 test_setopt( curl, CURLOPT_URL, url ); 237 printf( "CURLOPT_SHARE\n" ); 238 test_setopt( curl, CURLOPT_SHARE, share ); 239 printf( "CURLOPT_COOKIEJAR\n" ); 240 test_setopt( curl, CURLOPT_COOKIEJAR, JAR ); 241 242 printf( "PERFORM\n" ); 243 curl_easy_perform( curl ); 244 245 /* try to free share, expect to fail because share is in use*/ 246 printf( "try SHARE_CLEANUP...\n" ); 247 scode = curl_share_cleanup( share ); 248 if ( scode==CURLSHE_OK ) 249 { 250 fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); 251 share = NULL; 252 } else { 253 printf( "SHARE_CLEANUP failed, correct\n" ); 254 } 255 256test_cleanup: 257 258 /* clean up last handle */ 259 printf( "CLEANUP\n" ); 260 curl_easy_cleanup( curl ); 261 curl_slist_free_all( headers ); 262 263 curl_free(url); 264 265 /* free share */ 266 printf( "SHARE_CLEANUP\n" ); 267 scode = curl_share_cleanup( share ); 268 if ( scode!=CURLSHE_OK ) 269 fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", 270 (int)scode); 271 272 printf( "GLOBAL_CLEANUP\n" ); 273 curl_global_cleanup(); 274 275 return res; 276} 277 278