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