Imported Upstream version 7.40.0
[platform/upstream/curl.git] / tests / libtest / lib506.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, 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
28 static const char *HOSTHEADER = "Host: www.host.foo.com";
29 static const char *JAR = "log/jar506";
30 #define THREADS 2
31
32 /* struct containing data of a thread */
33 struct Tdata {
34   CURLSH *share;
35   char *url;
36 };
37
38 struct userdata {
39   char *text;
40   int counter;
41 };
42
43 int lock[3];
44
45 /* lock callback */
46 static void my_lock(CURL *handle, curl_lock_data data, curl_lock_access laccess,
47           void *useptr )
48 {
49   const char *what;
50   struct userdata *user = (struct userdata *)useptr;
51   int locknum;
52
53   (void)handle;
54   (void)laccess;
55
56   switch ( data ) {
57     case CURL_LOCK_DATA_SHARE:
58       what = "share";
59       locknum = 0;
60       break;
61     case CURL_LOCK_DATA_DNS:
62       what = "dns";
63       locknum = 1;
64       break;
65     case CURL_LOCK_DATA_COOKIE:
66       what = "cookie";
67       locknum = 2;
68       break;
69     default:
70       fprintf(stderr, "lock: no such data: %d\n", (int)data);
71       return;
72   }
73
74   /* detect locking of locked locks */
75   if(lock[locknum]) {
76     printf("lock: double locked %s\n", what);
77     return;
78   }
79   lock[locknum]++;
80
81   printf("lock:   %-6s [%s]: %d\n", what, user->text, user->counter);
82   user->counter++;
83 }
84
85 /* unlock callback */
86 static void my_unlock(CURL *handle, curl_lock_data data, void *useptr )
87 {
88   const char *what;
89   struct userdata *user = (struct userdata *)useptr;
90   int locknum;
91   (void)handle;
92   switch ( data ) {
93     case CURL_LOCK_DATA_SHARE:
94       what = "share";
95       locknum = 0;
96       break;
97     case CURL_LOCK_DATA_DNS:
98       what = "dns";
99       locknum = 1;
100       break;
101     case CURL_LOCK_DATA_COOKIE:
102       what = "cookie";
103       locknum = 2;
104       break;
105     default:
106       fprintf(stderr, "unlock: no such data: %d\n", (int)data);
107       return;
108   }
109
110   /* detect unlocking of unlocked locks */
111   if(!lock[locknum]) {
112     printf("unlock: double unlocked %s\n", what);
113     return;
114   }
115   lock[locknum]--;
116
117   printf("unlock: %-6s [%s]: %d\n", what, user->text, user->counter);
118   user->counter++;
119 }
120
121
122 /* build host entry */
123 static struct curl_slist *sethost(struct curl_slist *headers)
124 {
125   (void)headers;
126   return curl_slist_append(NULL, HOSTHEADER );
127 }
128
129
130 /* the dummy thread function */
131 static void *fire(void *ptr)
132 {
133   CURLcode code;
134   struct curl_slist *headers;
135   struct Tdata *tdata = (struct Tdata*)ptr;
136   CURL *curl;
137   int i=0;
138
139   if ((curl = curl_easy_init()) == NULL) {
140     fprintf(stderr, "curl_easy_init() failed\n");
141     return NULL;
142   }
143
144   headers = sethost(NULL);
145   curl_easy_setopt(curl, CURLOPT_VERBOSE,    1L);
146   curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
147   curl_easy_setopt(curl, CURLOPT_URL,        tdata->url);
148   printf( "CURLOPT_SHARE\n" );
149   curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share);
150
151   printf( "PERFORM\n" );
152   code = curl_easy_perform(curl);
153   if( code != CURLE_OK ) {
154     fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n",
155             tdata->url, i, (int)code);
156   }
157
158   printf( "CLEANUP\n" );
159   curl_easy_cleanup(curl);
160   curl_slist_free_all(headers);
161
162   return NULL;
163 }
164
165
166 /* build request url */
167 static char *suburl(const char *base, int i)
168 {
169   return curl_maprintf("%s%.4d", base, i);
170 }
171
172
173 /* test function */
174 int test(char *URL)
175 {
176   int res;
177   CURLSHcode scode = CURLSHE_OK;
178   CURLcode code = CURLE_OK;
179   char *url = NULL;
180   struct Tdata tdata;
181   CURL *curl;
182   CURLSH *share;
183   struct curl_slist *headers = NULL;
184   struct curl_slist *cookies = NULL;
185   struct curl_slist *next_cookie = NULL;
186   int i;
187   struct userdata user;
188
189   user.text = (char *)"Pigs in space";
190   user.counter = 0;
191
192   printf( "GLOBAL_INIT\n" );
193   if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
194     fprintf(stderr, "curl_global_init() failed\n");
195     return TEST_ERR_MAJOR_BAD;
196   }
197
198   /* prepare share */
199   printf( "SHARE_INIT\n" );
200   if ((share = curl_share_init()) == NULL) {
201     fprintf(stderr, "curl_share_init() failed\n");
202     curl_global_cleanup();
203     return TEST_ERR_MAJOR_BAD;
204   }
205
206   if ( CURLSHE_OK == scode ) {
207     printf( "CURLSHOPT_LOCKFUNC\n" );
208     scode = curl_share_setopt( share, CURLSHOPT_LOCKFUNC, my_lock);
209   }
210   if ( CURLSHE_OK == scode ) {
211     printf( "CURLSHOPT_UNLOCKFUNC\n" );
212     scode = curl_share_setopt( share, CURLSHOPT_UNLOCKFUNC, my_unlock);
213   }
214   if ( CURLSHE_OK == scode ) {
215     printf( "CURLSHOPT_USERDATA\n" );
216     scode = curl_share_setopt( share, CURLSHOPT_USERDATA, &user);
217   }
218   if ( CURLSHE_OK == scode ) {
219     printf( "CURL_LOCK_DATA_COOKIE\n" );
220     scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
221   }
222   if ( CURLSHE_OK == scode ) {
223     printf( "CURL_LOCK_DATA_DNS\n" );
224     scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
225   }
226
227   if ( CURLSHE_OK != scode ) {
228     fprintf(stderr, "curl_share_setopt() failed\n");
229     curl_share_cleanup(share);
230     curl_global_cleanup();
231     return TEST_ERR_MAJOR_BAD;
232   }
233
234   /* initial cookie manipulation */
235   if ((curl = curl_easy_init()) == NULL) {
236     fprintf(stderr, "curl_easy_init() failed\n");
237     curl_share_cleanup(share);
238     curl_global_cleanup();
239     return TEST_ERR_MAJOR_BAD;
240   }
241   printf( "CURLOPT_SHARE\n" );
242   test_setopt( curl, CURLOPT_SHARE,      share );
243   printf( "CURLOPT_COOKIELIST injected_and_clobbered\n" );
244   test_setopt( curl, CURLOPT_COOKIELIST,
245                "Set-Cookie: injected_and_clobbered=yes; "
246                "domain=host.foo.com; expires=Sat Feb 2 11:56:27 GMT 2030" );
247   printf( "CURLOPT_COOKIELIST ALL\n" );
248   test_setopt( curl, CURLOPT_COOKIELIST, "ALL" );
249   printf( "CURLOPT_COOKIELIST session\n" );
250   test_setopt( curl, CURLOPT_COOKIELIST, "Set-Cookie: session=elephants" );
251   printf( "CURLOPT_COOKIELIST injected\n" );
252   test_setopt( curl, CURLOPT_COOKIELIST,
253                "Set-Cookie: injected=yes; domain=host.foo.com; "
254                "expires=Sat Feb 2 11:56:27 GMT 2030" );
255   printf( "CURLOPT_COOKIELIST SESS\n" );
256   test_setopt( curl, CURLOPT_COOKIELIST, "SESS" );
257   printf( "CLEANUP\n" );
258   curl_easy_cleanup( curl );
259
260
261   res = 0;
262
263   /* start treads */
264   for (i=1; i<=THREADS; i++ ) {
265
266     /* set thread data */
267     tdata.url   = suburl( URL, i ); /* must be curl_free()d */
268     tdata.share = share;
269
270     /* simulate thread, direct call of "thread" function */
271     printf( "*** run %d\n",i );
272     fire( &tdata );
273
274     curl_free( tdata.url );
275
276   }
277
278
279   /* fetch a another one and save cookies */
280   printf( "*** run %d\n", i );
281   if ((curl = curl_easy_init()) == NULL) {
282     fprintf(stderr, "curl_easy_init() failed\n");
283     curl_share_cleanup(share);
284     curl_global_cleanup();
285     return TEST_ERR_MAJOR_BAD;
286   }
287
288   url = suburl( URL, i );
289   headers = sethost( NULL );
290   test_setopt( curl, CURLOPT_HTTPHEADER, headers );
291   test_setopt( curl, CURLOPT_URL,        url );
292   printf( "CURLOPT_SHARE\n" );
293   test_setopt( curl, CURLOPT_SHARE,      share );
294   printf( "CURLOPT_COOKIEJAR\n" );
295   test_setopt( curl, CURLOPT_COOKIEJAR,  JAR );
296   printf( "CURLOPT_COOKIELIST FLUSH\n" );
297   test_setopt( curl, CURLOPT_COOKIELIST, "FLUSH" );
298
299   printf( "PERFORM\n" );
300   curl_easy_perform( curl );
301
302   printf( "CLEANUP\n" );
303   curl_easy_cleanup( curl );
304   curl_free(url);
305   curl_slist_free_all( headers );
306
307   /* load cookies */
308   if ((curl = curl_easy_init()) == NULL) {
309     fprintf(stderr, "curl_easy_init() failed\n");
310     curl_share_cleanup(share);
311     curl_global_cleanup();
312     return TEST_ERR_MAJOR_BAD;
313   }
314   url = suburl( URL, i );
315   headers = sethost( NULL );
316   test_setopt( curl, CURLOPT_HTTPHEADER, headers );
317   test_setopt( curl, CURLOPT_URL,        url );
318   printf( "CURLOPT_SHARE\n" );
319   test_setopt( curl, CURLOPT_SHARE,      share );
320   printf( "CURLOPT_COOKIELIST ALL\n" );
321   test_setopt( curl, CURLOPT_COOKIELIST, "ALL" );
322   printf( "CURLOPT_COOKIEJAR\n" );
323   test_setopt( curl, CURLOPT_COOKIEFILE, JAR );
324   printf( "CURLOPT_COOKIELIST RELOAD\n" );
325   test_setopt( curl, CURLOPT_COOKIELIST, "RELOAD" );
326
327   code = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
328   if ( code != CURLE_OK )
329   {
330     fprintf(stderr, "curl_easy_getinfo() failed\n");
331     res = TEST_ERR_MAJOR_BAD;
332     goto test_cleanup;
333   }
334   printf("loaded cookies:\n");
335   if ( !cookies )
336   {
337     fprintf(stderr, "  reloading cookies from '%s' failed\n", JAR);
338     res = TEST_ERR_MAJOR_BAD;
339     goto test_cleanup;
340   }
341   printf("-----------------\n");
342   next_cookie = cookies;
343   while ( next_cookie )
344   {
345     printf( "  %s\n", next_cookie->data );
346     next_cookie = next_cookie->next;
347   }
348   printf("-----------------\n");
349   curl_slist_free_all( cookies );
350
351   /* try to free share, expect to fail because share is in use*/
352   printf( "try SHARE_CLEANUP...\n" );
353   scode = curl_share_cleanup( share );
354   if ( scode==CURLSHE_OK )
355   {
356     fprintf(stderr, "curl_share_cleanup succeed but error expected\n");
357     share = NULL;
358   } else {
359     printf( "SHARE_CLEANUP failed, correct\n" );
360   }
361
362 test_cleanup:
363
364   /* clean up last handle */
365   printf( "CLEANUP\n" );
366   curl_easy_cleanup( curl );
367   curl_slist_free_all( headers );
368   curl_free(url);
369
370   /* free share */
371   printf( "SHARE_CLEANUP\n" );
372   scode = curl_share_cleanup( share );
373   if ( scode!=CURLSHE_OK )
374     fprintf(stderr, "curl_share_cleanup failed, code errno %d\n",
375             (int)scode);
376
377   printf( "GLOBAL_CLEANUP\n" );
378   curl_global_cleanup();
379
380   return res;
381 }
382