1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2020, 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 ***************************************************************************/
22
23/* !checksrc! disable ASSIGNWITHINCONDITION 14 */
24
25/* Now include the curl_setup.h file from libcurl's private libdir (the source
26 version, but that might include "curl_config.h" from the build dir so we
27 need both of them in the include path), so that we get good in-depth
28 knowledge about the system we're building this on */
29
30#define CURL_NO_OLDIES
31
32#include "curl_setup.h"
33
34#include <curl/curl.h>
35
36#ifdef HAVE_SYS_SELECT_H
37/* since so many tests use select(), we can just as well include it here */
38#include <sys/select.h>
39#elif defined(HAVE_UNISTD_H)
40#include <unistd.h>
41#endif
42
43#ifdef TPF
44# include "select.h"
45#endif
46
47#include "curl_printf.h"
48
49#define test_setopt(A,B,C) \
50 if((res = curl_easy_setopt((A), (B), (C))) != CURLE_OK) \
51 goto test_cleanup
52
53#define test_multi_setopt(A,B,C) \
54 if((res = curl_multi_setopt((A), (B), (C))) != CURLE_OK) \
55 goto test_cleanup
56
57extern char *libtest_arg2; /* set by first.c to the argv[2] or NULL */
58extern char *libtest_arg3; /* set by first.c to the argv[3] or NULL */
59
60/* argc and argv as passed in to the main() function */
61extern int test_argc;
62extern char **test_argv;
63
64extern struct timeval tv_test_start; /* for test timing */
65
66extern int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc,
67 struct timeval *tv);
68
69extern void wait_ms(int ms); /* wait this many milliseconds */
70
71extern int test(char *URL); /* the actual test function provided by each
72 individual libXXX.c file */
73
74extern char *hexdump(const unsigned char *buffer, size_t len);
75
76#ifdef UNITTESTS
77extern int unitfail;
78#endif
79
80/*
81** TEST_ERR_* values must be greater than CURL_LAST CURLcode in order
82** to avoid confusion with any CURLcode or CURLMcode. These TEST_ERR_*
83** codes are returned to signal test specific situations and should
84** not get mixed with CURLcode or CURLMcode values.
85**
86** For portability reasons TEST_ERR_* values should be less than 127.
87*/
88
89#define TEST_ERR_MAJOR_BAD (CURLcode) 126
90#define TEST_ERR_RUNS_FOREVER (CURLcode) 125
91#define TEST_ERR_EASY_INIT (CURLcode) 124
92#define TEST_ERR_MULTI (CURLcode) 123
93#define TEST_ERR_NUM_HANDLES (CURLcode) 122
94#define TEST_ERR_SELECT (CURLcode) 121
95#define TEST_ERR_SUCCESS (CURLcode) 120
96#define TEST_ERR_FAILURE (CURLcode) 119
97#define TEST_ERR_USAGE (CURLcode) 118
98#define TEST_ERR_FOPEN (CURLcode) 117
99#define TEST_ERR_FSTAT (CURLcode) 116
100#define TEST_ERR_BAD_TIMEOUT (CURLcode) 115
101
102/*
103** Macros for test source code readability/maintainability.
104**
105** All of the following macros require that an int data type 'res' variable
106** exists in scope where macro is used, and that it has been initialized to
107** zero before the macro is used.
108**
109** exe_* and chk_* macros are helper macros not intended to be used from
110** outside of this header file. Arguments 'Y' and 'Z' of these represent
111** source code file and line number, while Arguments 'A', 'B', etc, are
112** the arguments used to actually call a libcurl function.
113**
114** All easy_* and multi_* macros call a libcurl function and evaluate if
115** the function has succeeded or failed. When the function succeeds 'res'
116** variable is not set nor cleared and program continues normal flow. On
117** the other hand if function fails 'res' variable is set and a jump to
118** label 'test_cleanup' is performed.
119**
120** Every easy_* and multi_* macros have a res_easy_* and res_multi_* macro
121** counterpart that operates in the same way with the exception that no
122** jump takes place in case of failure. res_easy_* and res_multi_* macros
123** should be immediately followed by checking if 'res' variable has been
124** set.
125**
126** 'res' variable when set will hold a CURLcode, CURLMcode, or any of the
127** TEST_ERR_* values defined above. It is advisable to return this value
128** as test result.
129*/
130
131/* ---------------------------------------------------------------- */
132
133#define exe_easy_init(A,Y,Z) do { \
134 if(((A) = curl_easy_init()) == NULL) { \
135 fprintf(stderr, "%s:%d curl_easy_init() failed\n", (Y), (Z)); \
136 res = TEST_ERR_EASY_INIT; \
137 } \
138} while(0)
139
140#define res_easy_init(A) \
141 exe_easy_init((A), (__FILE__), (__LINE__))
142
143#define chk_easy_init(A,Y,Z) do { \
144 exe_easy_init((A), (Y), (Z)); \
145 if(res) \
146 goto test_cleanup; \
147} while(0)
148
149#define easy_init(A) \
150 chk_easy_init((A), (__FILE__), (__LINE__))
151
152/* ---------------------------------------------------------------- */
153
154#define exe_multi_init(A,Y,Z) do { \
155 if(((A) = curl_multi_init()) == NULL) { \
156 fprintf(stderr, "%s:%d curl_multi_init() failed\n", (Y), (Z)); \
157 res = TEST_ERR_MULTI; \
158 } \
159} while(0)
160
161#define res_multi_init(A) \
162 exe_multi_init((A), (__FILE__), (__LINE__))
163
164#define chk_multi_init(A,Y,Z) do { \
165 exe_multi_init((A), (Y), (Z)); \
166 if(res) \
167 goto test_cleanup; \
168} while(0)
169
170#define multi_init(A) \
171 chk_multi_init((A), (__FILE__), (__LINE__))
172
173/* ---------------------------------------------------------------- */
174
175#define exe_easy_setopt(A,B,C,Y,Z) do { \
176 CURLcode ec; \
177 if((ec = curl_easy_setopt((A), (B), (C))) != CURLE_OK) { \
178 fprintf(stderr, "%s:%d curl_easy_setopt() failed, " \
179 "with code %d (%s)\n", \
180 (Y), (Z), (int)ec, curl_easy_strerror(ec)); \
181 res = ec; \
182 } \
183} while(0)
184
185#define res_easy_setopt(A, B, C) \
186 exe_easy_setopt((A), (B), (C), (__FILE__), (__LINE__))
187
188#define chk_easy_setopt(A, B, C, Y, Z) do { \
189 exe_easy_setopt((A), (B), (C), (Y), (Z)); \
190 if(res) \
191 goto test_cleanup; \
192} while(0)
193
194#define easy_setopt(A, B, C) \
195 chk_easy_setopt((A), (B), (C), (__FILE__), (__LINE__))
196
197/* ---------------------------------------------------------------- */
198
199#define exe_multi_setopt(A, B, C, Y, Z) do { \
200 CURLMcode ec; \
201 if((ec = curl_multi_setopt((A), (B), (C))) != CURLM_OK) { \
202 fprintf(stderr, "%s:%d curl_multi_setopt() failed, " \
203 "with code %d (%s)\n", \
204 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
205 res = TEST_ERR_MULTI; \
206 } \
207} while(0)
208
209#define res_multi_setopt(A,B,C) \
210 exe_multi_setopt((A), (B), (C), (__FILE__), (__LINE__))
211
212#define chk_multi_setopt(A,B,C,Y,Z) do { \
213 exe_multi_setopt((A), (B), (C), (Y), (Z)); \
214 if(res) \
215 goto test_cleanup; \
216} while(0)
217
218#define multi_setopt(A,B,C) \
219 chk_multi_setopt((A), (B), (C), (__FILE__), (__LINE__))
220
221/* ---------------------------------------------------------------- */
222
223#define exe_multi_add_handle(A,B,Y,Z) do { \
224 CURLMcode ec; \
225 if((ec = curl_multi_add_handle((A), (B))) != CURLM_OK) { \
226 fprintf(stderr, "%s:%d curl_multi_add_handle() failed, " \
227 "with code %d (%s)\n", \
228 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
229 res = TEST_ERR_MULTI; \
230 } \
231} while(0)
232
233#define res_multi_add_handle(A, B) \
234 exe_multi_add_handle((A), (B), (__FILE__), (__LINE__))
235
236#define chk_multi_add_handle(A, B, Y, Z) do { \
237 exe_multi_add_handle((A), (B), (Y), (Z)); \
238 if(res) \
239 goto test_cleanup; \
240} while(0)
241
242#define multi_add_handle(A, B) \
243 chk_multi_add_handle((A), (B), (__FILE__), (__LINE__))
244
245/* ---------------------------------------------------------------- */
246
247#define exe_multi_remove_handle(A,B,Y,Z) do { \
248 CURLMcode ec; \
249 if((ec = curl_multi_remove_handle((A), (B))) != CURLM_OK) { \
250 fprintf(stderr, "%s:%d curl_multi_remove_handle() failed, " \
251 "with code %d (%s)\n", \
252 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
253 res = TEST_ERR_MULTI; \
254 } \
255} while(0)
256
257#define res_multi_remove_handle(A, B) \
258 exe_multi_remove_handle((A), (B), (__FILE__), (__LINE__))
259
260#define chk_multi_remove_handle(A, B, Y, Z) do { \
261 exe_multi_remove_handle((A), (B), (Y), (Z)); \
262 if(res) \
263 goto test_cleanup; \
264} while(0)
265
266
267#define multi_remove_handle(A, B) \
268 chk_multi_remove_handle((A), (B), (__FILE__), (__LINE__))
269
270/* ---------------------------------------------------------------- */
271
272#define exe_multi_perform(A,B,Y,Z) do { \
273 CURLMcode ec; \
274 if((ec = curl_multi_perform((A), (B))) != CURLM_OK) { \
275 fprintf(stderr, "%s:%d curl_multi_perform() failed, " \
276 "with code %d (%s)\n", \
277 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
278 res = TEST_ERR_MULTI; \
279 } \
280 else if(*((B)) < 0) { \
281 fprintf(stderr, "%s:%d curl_multi_perform() succeeded, " \
282 "but returned invalid running_handles value (%d)\n", \
283 (Y), (Z), (int)*((B))); \
284 res = TEST_ERR_NUM_HANDLES; \
285 } \
286} while(0)
287
288#define res_multi_perform(A, B) \
289 exe_multi_perform((A), (B), (__FILE__), (__LINE__))
290
291#define chk_multi_perform(A, B, Y, Z) do { \
292 exe_multi_perform((A), (B), (Y), (Z)); \
293 if(res) \
294 goto test_cleanup; \
295} while(0)
296
297#define multi_perform(A,B) \
298 chk_multi_perform((A), (B), (__FILE__), (__LINE__))
299
300/* ---------------------------------------------------------------- */
301
302#define exe_multi_fdset(A, B, C, D, E, Y, Z) do { \
303 CURLMcode ec; \
304 if((ec = curl_multi_fdset((A), (B), (C), (D), (E))) != CURLM_OK) { \
305 fprintf(stderr, "%s:%d curl_multi_fdset() failed, " \
306 "with code %d (%s)\n", \
307 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
308 res = TEST_ERR_MULTI; \
309 } \
310 else if(*((E)) < -1) { \
311 fprintf(stderr, "%s:%d curl_multi_fdset() succeeded, " \
312 "but returned invalid max_fd value (%d)\n", \
313 (Y), (Z), (int)*((E))); \
314 res = TEST_ERR_NUM_HANDLES; \
315 } \
316} while(0)
317
318#define res_multi_fdset(A, B, C, D, E) \
319 exe_multi_fdset((A), (B), (C), (D), (E), (__FILE__), (__LINE__))
320
321#define chk_multi_fdset(A, B, C, D, E, Y, Z) do { \
322 exe_multi_fdset((A), (B), (C), (D), (E), (Y), (Z)); \
323 if(res) \
324 goto test_cleanup; \
325 } while(0)
326
327#define multi_fdset(A, B, C, D, E) \
328 chk_multi_fdset((A), (B), (C), (D), (E), (__FILE__), (__LINE__))
329
330/* ---------------------------------------------------------------- */
331
332#define exe_multi_timeout(A,B,Y,Z) do { \
333 CURLMcode ec; \
334 if((ec = curl_multi_timeout((A), (B))) != CURLM_OK) { \
335 fprintf(stderr, "%s:%d curl_multi_timeout() failed, " \
336 "with code %d (%s)\n", \
337 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
338 res = TEST_ERR_BAD_TIMEOUT; \
339 } \
340 else if(*((B)) < -1L) { \
341 fprintf(stderr, "%s:%d curl_multi_timeout() succeeded, " \
342 "but returned invalid timeout value (%ld)\n", \
343 (Y), (Z), (long)*((B))); \
344 res = TEST_ERR_BAD_TIMEOUT; \
345 } \
346} while(0)
347
348#define res_multi_timeout(A, B) \
349 exe_multi_timeout((A), (B), (__FILE__), (__LINE__))
350
351#define chk_multi_timeout(A, B, Y, Z) do { \
352 exe_multi_timeout((A), (B), (Y), (Z)); \
353 if(res) \
354 goto test_cleanup; \
355 } while(0)
356
357#define multi_timeout(A, B) \
358 chk_multi_timeout((A), (B), (__FILE__), (__LINE__))
359
360/* ---------------------------------------------------------------- */
361
362#define exe_multi_poll(A,B,C,D,E,Y,Z) do { \
363 CURLMcode ec; \
364 if((ec = curl_multi_poll((A), (B), (C), (D), (E))) != CURLM_OK) { \
365 fprintf(stderr, "%s:%d curl_multi_poll() failed, " \
366 "with code %d (%s)\n", \
367 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
368 res = TEST_ERR_MULTI; \
369 } \
370 else if(*((E)) < 0) { \
371 fprintf(stderr, "%s:%d curl_multi_poll() succeeded, " \
372 "but returned invalid numfds value (%d)\n", \
373 (Y), (Z), (int)*((E))); \
374 res = TEST_ERR_NUM_HANDLES; \
375 } \
376} while(0)
377
378#define res_multi_poll(A, B, C, D, E) \
379 exe_multi_poll((A), (B), (C), (D), (E), (__FILE__), (__LINE__))
380
381#define chk_multi_poll(A, B, C, D, E, Y, Z) do { \
382 exe_multi_poll((A), (B), (C), (D), (E), (Y), (Z)); \
383 if(res) \
384 goto test_cleanup; \
385} while(0)
386
387#define multi_poll(A, B, C, D, E) \
388 chk_multi_poll((A), (B), (C), (D), (E), (__FILE__), (__LINE__))
389
390/* ---------------------------------------------------------------- */
391
392#define exe_multi_wakeup(A,Y,Z) do { \
393 CURLMcode ec; \
394 if((ec = curl_multi_wakeup((A))) != CURLM_OK) { \
395 fprintf(stderr, "%s:%d curl_multi_wakeup() failed, " \
396 "with code %d (%s)\n", \
397 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \
398 res = TEST_ERR_MULTI; \
399 } \
400} while(0)
401
402#define res_multi_wakeup(A) \
403 exe_multi_wakeup((A), (__FILE__), (__LINE__))
404
405#define chk_multi_wakeup(A, Y, Z) do { \
406 exe_multi_wakeup((A), (Y), (Z)); \
407 if(res) \
408 goto test_cleanup; \
409} while(0)
410
411#define multi_wakeup(A) \
412 chk_multi_wakeup((A), (__FILE__), (__LINE__))
413
414/* ---------------------------------------------------------------- */
415
416#define exe_select_test(A, B, C, D, E, Y, Z) do { \
417 int ec; \
418 if(select_wrapper((A), (B), (C), (D), (E)) == -1) { \
419 ec = SOCKERRNO; \
420 fprintf(stderr, "%s:%d select() failed, with " \
421 "errno %d (%s)\n", \
422 (Y), (Z), ec, strerror(ec)); \
423 res = TEST_ERR_SELECT; \
424 } \
425 } while(0)
426
427#define res_select_test(A, B, C, D, E) \
428 exe_select_test((A), (B), (C), (D), (E), (__FILE__), (__LINE__))
429
430#define chk_select_test(A, B, C, D, E, Y, Z) do { \
431 exe_select_test((A), (B), (C), (D), (E), (Y), (Z)); \
432 if(res) \
433 goto test_cleanup; \
434 } while(0)
435
436#define select_test(A, B, C, D, E) \
437 chk_select_test((A), (B), (C), (D), (E), (__FILE__), (__LINE__))
438
439/* ---------------------------------------------------------------- */
440
441#define start_test_timing() do { \
442 tv_test_start = tutil_tvnow(); \
443} while(0)
444
445#define exe_test_timedout(Y,Z) do { \
446 if(tutil_tvdiff(tutil_tvnow(), tv_test_start) > TEST_HANG_TIMEOUT) { \
447 fprintf(stderr, "%s:%d ABORTING TEST, since it seems " \
448 "that it would have run forever.\n", (Y), (Z)); \
449 res = TEST_ERR_RUNS_FOREVER; \
450 } \
451} while(0)
452
453#define res_test_timedout() \
454 exe_test_timedout((__FILE__), (__LINE__))
455
456#define chk_test_timedout(Y, Z) do { \
457 exe_test_timedout(Y, Z); \
458 if(res) \
459 goto test_cleanup; \
460 } while(0)
461
462#define abort_on_test_timeout() \
463 chk_test_timedout((__FILE__), (__LINE__))
464
465/* ---------------------------------------------------------------- */
466
467#define exe_global_init(A,Y,Z) do { \
468 CURLcode ec; \
469 if((ec = curl_global_init((A))) != CURLE_OK) { \
470 fprintf(stderr, "%s:%d curl_global_init() failed, " \
471 "with code %d (%s)\n", \
472 (Y), (Z), (int)ec, curl_easy_strerror(ec)); \
473 res = ec; \
474 } \
475} while(0)
476
477#define res_global_init(A) \
478 exe_global_init((A), (__FILE__), (__LINE__))
479
480#define chk_global_init(A, Y, Z) do { \
481 exe_global_init((A), (Y), (Z)); \
482 if(res) \
483 return res; \
484 } while(0)
485
486/* global_init() is different than other macros. In case of
487 failure it 'return's instead of going to 'test_cleanup'. */
488
489#define global_init(A) \
490 chk_global_init((A), (__FILE__), (__LINE__))
491
492/* ---------------------------------------------------------------- */
493