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