xref: /aosp_15_r20/external/curl/tests/libtest/lib3207.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "test.h"
25*6236dae4SAndroid Build Coastguard Worker #include "testutil.h"
26*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
27*6236dae4SAndroid Build Coastguard Worker 
28*6236dae4SAndroid Build Coastguard Worker #include <stdio.h>
29*6236dae4SAndroid Build Coastguard Worker 
30*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
31*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX)
32*6236dae4SAndroid Build Coastguard Worker #include <pthread.h>
33*6236dae4SAndroid Build Coastguard Worker #endif
34*6236dae4SAndroid Build Coastguard Worker #include "curl_threads.h"
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker 
37*6236dae4SAndroid Build Coastguard Worker #define CAINFO libtest_arg2
38*6236dae4SAndroid Build Coastguard Worker #define THREAD_SIZE 16
39*6236dae4SAndroid Build Coastguard Worker #define PER_THREAD_SIZE 8
40*6236dae4SAndroid Build Coastguard Worker 
41*6236dae4SAndroid Build Coastguard Worker struct Ctx {
42*6236dae4SAndroid Build Coastguard Worker   const char *URL;
43*6236dae4SAndroid Build Coastguard Worker   CURLSH *share;
44*6236dae4SAndroid Build Coastguard Worker   int result;
45*6236dae4SAndroid Build Coastguard Worker   int thread_id;
46*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *contents;
47*6236dae4SAndroid Build Coastguard Worker };
48*6236dae4SAndroid Build Coastguard Worker 
write_memory_callback(char * contents,size_t size,size_t nmemb,void * userp)49*6236dae4SAndroid Build Coastguard Worker static size_t write_memory_callback(char *contents, size_t size,
50*6236dae4SAndroid Build Coastguard Worker                                     size_t nmemb, void *userp)
51*6236dae4SAndroid Build Coastguard Worker {
52*6236dae4SAndroid Build Coastguard Worker   /* append the data to contents */
53*6236dae4SAndroid Build Coastguard Worker   size_t realsize = size * nmemb;
54*6236dae4SAndroid Build Coastguard Worker   struct Ctx *mem = (struct Ctx *)userp;
55*6236dae4SAndroid Build Coastguard Worker   char *data = (char *)malloc(realsize + 1);
56*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *item_append = NULL;
57*6236dae4SAndroid Build Coastguard Worker   if(!data) {
58*6236dae4SAndroid Build Coastguard Worker     printf("not enough memory (malloc returned NULL)\n");
59*6236dae4SAndroid Build Coastguard Worker     return 0;
60*6236dae4SAndroid Build Coastguard Worker   }
61*6236dae4SAndroid Build Coastguard Worker   memcpy(data, contents, realsize);
62*6236dae4SAndroid Build Coastguard Worker   data[realsize] = '\0';
63*6236dae4SAndroid Build Coastguard Worker   item_append = curl_slist_append(mem->contents, data);
64*6236dae4SAndroid Build Coastguard Worker   free(data);
65*6236dae4SAndroid Build Coastguard Worker   if(item_append) {
66*6236dae4SAndroid Build Coastguard Worker     mem->contents = item_append;
67*6236dae4SAndroid Build Coastguard Worker   }
68*6236dae4SAndroid Build Coastguard Worker   else {
69*6236dae4SAndroid Build Coastguard Worker     printf("not enough memory (curl_slist_append returned NULL)\n");
70*6236dae4SAndroid Build Coastguard Worker     return 0;
71*6236dae4SAndroid Build Coastguard Worker   }
72*6236dae4SAndroid Build Coastguard Worker   return realsize;
73*6236dae4SAndroid Build Coastguard Worker }
74*6236dae4SAndroid Build Coastguard Worker 
75*6236dae4SAndroid Build Coastguard Worker static
76*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
77*6236dae4SAndroid Build Coastguard Worker #if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
78*6236dae4SAndroid Build Coastguard Worker DWORD
79*6236dae4SAndroid Build Coastguard Worker #else
80*6236dae4SAndroid Build Coastguard Worker unsigned int
81*6236dae4SAndroid Build Coastguard Worker #endif
82*6236dae4SAndroid Build Coastguard Worker CURL_STDCALL
83*6236dae4SAndroid Build Coastguard Worker #else
84*6236dae4SAndroid Build Coastguard Worker unsigned int
85*6236dae4SAndroid Build Coastguard Worker #endif
test_thread(void * ptr)86*6236dae4SAndroid Build Coastguard Worker test_thread(void *ptr)
87*6236dae4SAndroid Build Coastguard Worker {
88*6236dae4SAndroid Build Coastguard Worker   struct Ctx *ctx = (struct Ctx *)ptr;
89*6236dae4SAndroid Build Coastguard Worker   CURLcode res = CURLE_OK;
90*6236dae4SAndroid Build Coastguard Worker 
91*6236dae4SAndroid Build Coastguard Worker   int i;
92*6236dae4SAndroid Build Coastguard Worker 
93*6236dae4SAndroid Build Coastguard Worker   /* Loop the transfer and cleanup the handle properly every lap. This will
94*6236dae4SAndroid Build Coastguard Worker      still reuse ssl session since the pool is in the shared object! */
95*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < PER_THREAD_SIZE; i++) {
96*6236dae4SAndroid Build Coastguard Worker     CURL *curl = curl_easy_init();
97*6236dae4SAndroid Build Coastguard Worker     if(curl) {
98*6236dae4SAndroid Build Coastguard Worker       curl_easy_setopt(curl, CURLOPT_URL, (char *)ctx->URL);
99*6236dae4SAndroid Build Coastguard Worker 
100*6236dae4SAndroid Build Coastguard Worker       /* use the share object */
101*6236dae4SAndroid Build Coastguard Worker       curl_easy_setopt(curl, CURLOPT_SHARE, ctx->share);
102*6236dae4SAndroid Build Coastguard Worker       curl_easy_setopt(curl, CURLOPT_CAINFO, CAINFO);
103*6236dae4SAndroid Build Coastguard Worker 
104*6236dae4SAndroid Build Coastguard Worker       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback);
105*6236dae4SAndroid Build Coastguard Worker       curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr);
106*6236dae4SAndroid Build Coastguard Worker       curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
107*6236dae4SAndroid Build Coastguard Worker 
108*6236dae4SAndroid Build Coastguard Worker       /* Perform the request, res will get the return code */
109*6236dae4SAndroid Build Coastguard Worker       res = curl_easy_perform(curl);
110*6236dae4SAndroid Build Coastguard Worker 
111*6236dae4SAndroid Build Coastguard Worker       /* always cleanup */
112*6236dae4SAndroid Build Coastguard Worker       curl_easy_cleanup(curl);
113*6236dae4SAndroid Build Coastguard Worker       /* Check for errors */
114*6236dae4SAndroid Build Coastguard Worker       if(res != CURLE_OK) {
115*6236dae4SAndroid Build Coastguard Worker         fprintf(stderr, "curl_easy_perform() failed: %s\n",
116*6236dae4SAndroid Build Coastguard Worker                 curl_easy_strerror(res));
117*6236dae4SAndroid Build Coastguard Worker         goto test_cleanup;
118*6236dae4SAndroid Build Coastguard Worker       }
119*6236dae4SAndroid Build Coastguard Worker     }
120*6236dae4SAndroid Build Coastguard Worker   }
121*6236dae4SAndroid Build Coastguard Worker 
122*6236dae4SAndroid Build Coastguard Worker test_cleanup:
123*6236dae4SAndroid Build Coastguard Worker   ctx->result = (int)res;
124*6236dae4SAndroid Build Coastguard Worker   return 0;
125*6236dae4SAndroid Build Coastguard Worker }
126*6236dae4SAndroid Build Coastguard Worker 
127*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
128*6236dae4SAndroid Build Coastguard Worker 
test_lock(CURL * handle,curl_lock_data data,curl_lock_access laccess,void * useptr)129*6236dae4SAndroid Build Coastguard Worker static void test_lock(CURL *handle, curl_lock_data data,
130*6236dae4SAndroid Build Coastguard Worker                       curl_lock_access laccess, void *useptr)
131*6236dae4SAndroid Build Coastguard Worker {
132*6236dae4SAndroid Build Coastguard Worker   curl_mutex_t *mutexes = (curl_mutex_t*) useptr;
133*6236dae4SAndroid Build Coastguard Worker   (void)handle;
134*6236dae4SAndroid Build Coastguard Worker   (void)laccess;
135*6236dae4SAndroid Build Coastguard Worker   Curl_mutex_acquire(&mutexes[data]);
136*6236dae4SAndroid Build Coastguard Worker }
137*6236dae4SAndroid Build Coastguard Worker 
test_unlock(CURL * handle,curl_lock_data data,void * useptr)138*6236dae4SAndroid Build Coastguard Worker static void test_unlock(CURL *handle, curl_lock_data data, void *useptr)
139*6236dae4SAndroid Build Coastguard Worker {
140*6236dae4SAndroid Build Coastguard Worker   curl_mutex_t *mutexes = (curl_mutex_t*) useptr;
141*6236dae4SAndroid Build Coastguard Worker   (void)handle;
142*6236dae4SAndroid Build Coastguard Worker   Curl_mutex_release(&mutexes[data]);
143*6236dae4SAndroid Build Coastguard Worker }
144*6236dae4SAndroid Build Coastguard Worker 
execute(CURLSH * share,struct Ctx * ctx)145*6236dae4SAndroid Build Coastguard Worker static void execute(CURLSH *share, struct Ctx *ctx)
146*6236dae4SAndroid Build Coastguard Worker {
147*6236dae4SAndroid Build Coastguard Worker   int i;
148*6236dae4SAndroid Build Coastguard Worker   curl_mutex_t mutexes[CURL_LOCK_DATA_LAST - 1];
149*6236dae4SAndroid Build Coastguard Worker   curl_thread_t thread[THREAD_SIZE];
150*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < CURL_LOCK_DATA_LAST - 1; i++) {
151*6236dae4SAndroid Build Coastguard Worker     Curl_mutex_init(&mutexes[i]);
152*6236dae4SAndroid Build Coastguard Worker   }
153*6236dae4SAndroid Build Coastguard Worker   curl_share_setopt(share, CURLSHOPT_LOCKFUNC, test_lock);
154*6236dae4SAndroid Build Coastguard Worker   curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, test_unlock);
155*6236dae4SAndroid Build Coastguard Worker   curl_share_setopt(share, CURLSHOPT_USERDATA, (void *)mutexes);
156*6236dae4SAndroid Build Coastguard Worker   curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
157*6236dae4SAndroid Build Coastguard Worker 
158*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < THREAD_SIZE; i++) {
159*6236dae4SAndroid Build Coastguard Worker     thread[i] = Curl_thread_create(test_thread, (void *)&ctx[i]);
160*6236dae4SAndroid Build Coastguard Worker   }
161*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < THREAD_SIZE; i++) {
162*6236dae4SAndroid Build Coastguard Worker     if(thread[i]) {
163*6236dae4SAndroid Build Coastguard Worker       Curl_thread_join(&thread[i]);
164*6236dae4SAndroid Build Coastguard Worker       Curl_thread_destroy(thread[i]);
165*6236dae4SAndroid Build Coastguard Worker     }
166*6236dae4SAndroid Build Coastguard Worker   }
167*6236dae4SAndroid Build Coastguard Worker   curl_share_setopt(share, CURLSHOPT_LOCKFUNC, NULL);
168*6236dae4SAndroid Build Coastguard Worker   curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, NULL);
169*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < CURL_LOCK_DATA_LAST - 1; i++) {
170*6236dae4SAndroid Build Coastguard Worker     Curl_mutex_destroy(&mutexes[i]);
171*6236dae4SAndroid Build Coastguard Worker   }
172*6236dae4SAndroid Build Coastguard Worker }
173*6236dae4SAndroid Build Coastguard Worker 
174*6236dae4SAndroid Build Coastguard Worker #else /* without pthread, run serially */
175*6236dae4SAndroid Build Coastguard Worker 
execute(CURLSH * share,struct Ctx * ctx)176*6236dae4SAndroid Build Coastguard Worker static void execute(CURLSH *share, struct Ctx *ctx)
177*6236dae4SAndroid Build Coastguard Worker {
178*6236dae4SAndroid Build Coastguard Worker   int i;
179*6236dae4SAndroid Build Coastguard Worker   (void) share;
180*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < THREAD_SIZE; i++) {
181*6236dae4SAndroid Build Coastguard Worker     test_thread((void *)&ctx[i]);
182*6236dae4SAndroid Build Coastguard Worker   }
183*6236dae4SAndroid Build Coastguard Worker }
184*6236dae4SAndroid Build Coastguard Worker 
185*6236dae4SAndroid Build Coastguard Worker #endif
186*6236dae4SAndroid Build Coastguard Worker 
test(char * URL)187*6236dae4SAndroid Build Coastguard Worker CURLcode test(char *URL)
188*6236dae4SAndroid Build Coastguard Worker {
189*6236dae4SAndroid Build Coastguard Worker   int res = 0;
190*6236dae4SAndroid Build Coastguard Worker   int i;
191*6236dae4SAndroid Build Coastguard Worker   CURLSH* share;
192*6236dae4SAndroid Build Coastguard Worker   struct Ctx ctx[THREAD_SIZE];
193*6236dae4SAndroid Build Coastguard Worker 
194*6236dae4SAndroid Build Coastguard Worker   curl_global_init(CURL_GLOBAL_ALL);
195*6236dae4SAndroid Build Coastguard Worker 
196*6236dae4SAndroid Build Coastguard Worker   share = curl_share_init();
197*6236dae4SAndroid Build Coastguard Worker   if(!share) {
198*6236dae4SAndroid Build Coastguard Worker     fprintf(stderr, "curl_share_init() failed\n");
199*6236dae4SAndroid Build Coastguard Worker     goto test_cleanup;
200*6236dae4SAndroid Build Coastguard Worker   }
201*6236dae4SAndroid Build Coastguard Worker 
202*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < THREAD_SIZE; i++) {
203*6236dae4SAndroid Build Coastguard Worker     ctx[i].share = share;
204*6236dae4SAndroid Build Coastguard Worker     ctx[i].URL = URL;
205*6236dae4SAndroid Build Coastguard Worker     ctx[i].thread_id = i;
206*6236dae4SAndroid Build Coastguard Worker     ctx[i].result = 0;
207*6236dae4SAndroid Build Coastguard Worker     ctx[i].contents = NULL;
208*6236dae4SAndroid Build Coastguard Worker   }
209*6236dae4SAndroid Build Coastguard Worker 
210*6236dae4SAndroid Build Coastguard Worker   execute(share, ctx);
211*6236dae4SAndroid Build Coastguard Worker 
212*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < THREAD_SIZE; i++) {
213*6236dae4SAndroid Build Coastguard Worker     if(ctx[i].result) {
214*6236dae4SAndroid Build Coastguard Worker       res = ctx[i].result;
215*6236dae4SAndroid Build Coastguard Worker     }
216*6236dae4SAndroid Build Coastguard Worker     else {
217*6236dae4SAndroid Build Coastguard Worker       struct curl_slist *item = ctx[i].contents;
218*6236dae4SAndroid Build Coastguard Worker       while(item) {
219*6236dae4SAndroid Build Coastguard Worker         printf("%s", item->data);
220*6236dae4SAndroid Build Coastguard Worker         item = item->next;
221*6236dae4SAndroid Build Coastguard Worker       }
222*6236dae4SAndroid Build Coastguard Worker     }
223*6236dae4SAndroid Build Coastguard Worker     curl_slist_free_all(ctx[i].contents);
224*6236dae4SAndroid Build Coastguard Worker   }
225*6236dae4SAndroid Build Coastguard Worker 
226*6236dae4SAndroid Build Coastguard Worker test_cleanup:
227*6236dae4SAndroid Build Coastguard Worker   if(share)
228*6236dae4SAndroid Build Coastguard Worker     curl_share_cleanup(share);
229*6236dae4SAndroid Build Coastguard Worker   curl_global_cleanup();
230*6236dae4SAndroid Build Coastguard Worker   return (CURLcode)res;
231*6236dae4SAndroid Build Coastguard Worker }
232