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