xref: /curl/tests/libtest/lib526.c (revision 25cbc2f7)
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 /*
25  * This code sets up multiple easy handles that transfer a single file from
26  * the same URL, in a serial manner after each other. Due to the connection
27  * sharing within the multi handle all transfers are performed on the same
28  * persistent connection.
29  *
30  * This source code is used for lib526, lib527 and lib532 with only #ifdefs
31  * controlling the small differences.
32  *
33  * - lib526 closes all easy handles after
34  *   they all have transferred the file over the single connection
35  * - lib527 closes each easy handle after each single transfer.
36  * - lib532 uses only a single easy handle that is removed, reset and then
37  *   re-added for each transfer
38  *
39  * Test case 526, 527 and 532 use FTP, while test 528 uses the lib526 tool but
40  * with HTTP.
41  */
42 
43 #include "test.h"
44 
45 #include <fcntl.h>
46 
47 #include "testutil.h"
48 #include "warnless.h"
49 #include "memdebug.h"
50 
51 #define TEST_HANG_TIMEOUT 60 * 1000
52 
53 #define NUM_HANDLES 4
54 
test(char * URL)55 CURLcode test(char *URL)
56 {
57   CURLcode res = CURLE_OK;
58   CURL *curl[NUM_HANDLES];
59   int running;
60   CURLM *m = NULL;
61   int current = 0;
62   int i;
63 
64   for(i = 0; i < NUM_HANDLES; i++)
65     curl[i] = NULL;
66 
67   start_test_timing();
68 
69   global_init(CURL_GLOBAL_ALL);
70 
71   /* get NUM_HANDLES easy handles */
72   for(i = 0; i < NUM_HANDLES; i++) {
73     easy_init(curl[i]);
74     /* specify target */
75     easy_setopt(curl[i], CURLOPT_URL, URL);
76     /* go verbose */
77     easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
78   }
79 
80   multi_init(m);
81 
82   multi_add_handle(m, curl[current]);
83 
84   fprintf(stderr, "Start at URL 0\n");
85 
86   for(;;) {
87     struct timeval interval;
88     fd_set rd, wr, exc;
89     int maxfd = -99;
90 
91     interval.tv_sec = 1;
92     interval.tv_usec = 0;
93 
94     multi_perform(m, &running);
95 
96     abort_on_test_timeout();
97 
98     if(!running) {
99 #ifdef LIB527
100       /* NOTE: this code does not remove the handle from the multi handle
101          here, which would be the nice, sane and documented way of working.
102          This however tests that the API survives this abuse gracefully. */
103       curl_easy_cleanup(curl[current]);
104       curl[current] = NULL;
105 #endif
106       if(++current < NUM_HANDLES) {
107         fprintf(stderr, "Advancing to URL %d\n", current);
108 #ifdef LIB532
109         /* first remove the only handle we use */
110         curl_multi_remove_handle(m, curl[0]);
111 
112         /* make us reuse the same handle all the time, and try resetting
113            the handle first too */
114         curl_easy_reset(curl[0]);
115         easy_setopt(curl[0], CURLOPT_URL, URL);
116         /* go verbose */
117         easy_setopt(curl[0], CURLOPT_VERBOSE, 1L);
118 
119         /* re-add it */
120         multi_add_handle(m, curl[0]);
121 #else
122         multi_add_handle(m, curl[current]);
123 #endif
124       }
125       else {
126         break; /* done */
127       }
128     }
129 
130     FD_ZERO(&rd);
131     FD_ZERO(&wr);
132     FD_ZERO(&exc);
133 
134     multi_fdset(m, &rd, &wr, &exc, &maxfd);
135 
136     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
137 
138     select_test(maxfd + 1, &rd, &wr, &exc, &interval);
139 
140     abort_on_test_timeout();
141   }
142 
143 test_cleanup:
144 
145 #if defined(LIB526)
146 
147   /* test 526 and 528 */
148   /* proper cleanup sequence - type PB */
149 
150   for(i = 0; i < NUM_HANDLES; i++) {
151     curl_multi_remove_handle(m, curl[i]);
152     curl_easy_cleanup(curl[i]);
153   }
154   curl_multi_cleanup(m);
155   curl_global_cleanup();
156 
157 #elif defined(LIB527)
158 
159   /* test 527 */
160 
161   /* Upon non-failure test flow the easy's have already been cleanup'ed. In
162      case there is a failure we arrive here with easy's that have not been
163      cleanup'ed yet, in this case we have to cleanup them or otherwise these
164      will be leaked, let's use undocumented cleanup sequence - type UB */
165 
166   if(res != CURLE_OK)
167     for(i = 0; i < NUM_HANDLES; i++)
168       curl_easy_cleanup(curl[i]);
169 
170   curl_multi_cleanup(m);
171   curl_global_cleanup();
172 
173 #elif defined(LIB532)
174 
175   /* test 532 */
176   /* undocumented cleanup sequence - type UB */
177 
178   for(i = 0; i < NUM_HANDLES; i++)
179     curl_easy_cleanup(curl[i]);
180   curl_multi_cleanup(m);
181   curl_global_cleanup();
182 
183 #endif
184 
185   return res;
186 }
187