xref: /curl/tests/libtest/mk-lib1521.pl (revision 71cf0d1f)
1#!/usr/bin/env perl
2#***************************************************************************
3#                                  _   _ ____  _
4#  Project                     ___| | | |  _ \| |
5#                             / __| | | | |_) | |
6#                            | (__| |_| |  _ <| |___
7#                             \___|\___/|_| \_\_____|
8#
9# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
10#
11# This software is licensed as described in the file COPYING, which
12# you should have received as part of this distribution. The terms
13# are also available at https://curl.se/docs/copyright.html.
14#
15# You may opt to use, copy, modify, merge, publish, distribute and/or sell
16# copies of the Software, and permit persons to whom the Software is
17# furnished to do so, under the terms of the COPYING file.
18#
19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20# KIND, either express or implied.
21#
22# SPDX-License-Identifier: curl
23#
24###########################################################################
25
26# Usage:
27#   perl mk-lib1521.pl < ../../include/curl/curl.h > lib1521.c
28
29# minimum and maximum long signed values
30my $minlong = "LONG_MIN";
31my $maxlong = "LONG_MAX";
32# maximum curl_off_t
33my $maxofft = "CURL_OFF_T_MAX";
34my $line = "";
35my $incomment = 0;
36
37# Options allowed to return CURLE_BAD_FUNCTION_ARGUMENT if given a string they
38# do not recognize as valid
39my @bad_function_argument = (
40    'CURLOPT_DNS_LOCAL_IP4',
41    'CURLOPT_DNS_LOCAL_IP6',
42    'CURLOPT_DNS_SERVERS',
43    'CURLOPT_PROXY_TLSAUTH_TYPE',
44    'CURLOPT_SSLENGINE',
45    'CURLOPT_TLSAUTH_TYPE',
46);
47
48# Options allowed to return CURLE_UNSUPPORTED_PROTOCOL if given a string they
49# do not recognize as valid
50my @unsupported_protocol = (
51    'CURLOPT_PROTOCOLS_STR',
52    'CURLOPT_REDIR_PROTOCOLS_STR',
53    );
54
55# Options allowed to return CURLE_SSL_ENGINE_NOTFOUND if given a string they
56# do not recognize as valid
57my @ssl_engine_notfound = (
58    'CURLOPT_SSLENGINE',
59    );
60
61# Options allowed to return CURLE_UNSUPPORTED_PROTOCOL if given a bad
62# numerical input they do not recognize as valid
63my @unsupported_protocol_num = (
64    'CURLOPT_HTTP_VERSION',
65    );
66
67# Options allowed to return CURLE_NOT_BUILT_IN if given a bad
68# numerical input they do not recognize as valid
69my @not_built_in_num = (
70    'CURLOPT_HTTPAUTH',
71    'CURLOPT_PROXYAUTH',
72    'CURLOPT_SOCKS5_AUTH',
73    );
74
75
76#
77# Generate a set of string checks
78#
79
80my $allowedstringerrors = <<MOO
81  switch(code) {
82  case CURLE_BAD_FUNCTION_ARGUMENT:
83MOO
84    ;
85
86for my $o (@bad_function_argument) {
87    $allowedstringerrors .= <<MOO
88    if(!strcmp("$o", name))
89      return;
90MOO
91        ;
92}
93
94$allowedstringerrors .= <<MOO
95     break;
96MOO
97    ;
98
99$allowedstringerrors .= <<MOO
100  case CURLE_UNSUPPORTED_PROTOCOL:
101MOO
102    ;
103for my $o (@unsupported_protocol) {
104    $allowedstringerrors .= <<MOO
105    if(!strcmp("$o", name))
106      return;
107MOO
108        ;
109}
110$allowedstringerrors .= <<MOO
111    break;
112MOO
113    ;
114
115$allowedstringerrors .= <<MOO
116  case CURLE_SSL_ENGINE_NOTFOUND:
117MOO
118    ;
119for my $o (@ssl_engine_notfound) {
120    $allowedstringerrors .= <<MOO
121    if(!strcmp("$o", name))
122      return;
123MOO
124        ;
125}
126$allowedstringerrors .= <<MOO
127    break;
128  default:
129    break;
130  }
131MOO
132    ;
133
134#
135# Generate a set of string checks
136#
137
138my $allowednumerrors = <<MOO
139  switch(code) {
140  case CURLE_UNSUPPORTED_PROTOCOL:
141MOO
142    ;
143
144for my $o (@unsupported_protocol_num) {
145    $allowednumerrors .= <<MOO
146    if(!strcmp("$o", name))
147      return;
148MOO
149        ;
150}
151
152$allowednumerrors .= <<MOO
153    break;
154  case CURLE_NOT_BUILT_IN:
155MOO
156    ;
157
158for my $o (@not_built_in_num) {
159    $allowednumerrors .= <<MOO
160    if(!strcmp("$o", name))
161      return;
162MOO
163        ;
164}
165
166$allowednumerrors .= <<MOO
167    break;
168  default:
169    break;
170  }
171MOO
172    ;
173
174print <<HEADER
175/***************************************************************************
176 *                                  _   _ ____  _
177 *  Project                     ___| | | |  _ \\| |
178 *                             / __| | | | |_) | |
179 *                            | (__| |_| |  _ <| |___
180 *                             \\___|\\___/|_| \\_\\_____|
181 *
182 * Copyright (C) Daniel Stenberg, <daniel\@haxx.se>, et al.
183 *
184 * This software is licensed as described in the file COPYING, which
185 * you should have received as part of this distribution. The terms
186 * are also available at https://curl.se/docs/copyright.html.
187 *
188 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
189 * copies of the Software, and permit persons to whom the Software is
190 * furnished to do so, under the terms of the COPYING file.
191 *
192 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
193 * KIND, either express or implied.
194 *
195 * SPDX-License-Identifier: curl
196 *
197 ***************************************************************************/
198#include "test.h"
199#include "memdebug.h"
200#include <limits.h>
201
202/* This source code is generated by mk-lib1521.pl ! */
203
204struct testdata {
205    char *blaha;
206};
207
208#define LO $minlong
209#define HI $maxlong
210#define OFF_LO (curl_off_t) LO
211#define OFF_HI (curl_off_t) $maxofft
212#define OFF_NO (curl_off_t) 0
213
214static size_t writecb(char *buffer, size_t size, size_t nitems,
215                      void *outstream)
216{
217  (void)buffer;
218  (void)size;
219  (void)nitems;
220  (void)outstream;
221  return 0;
222}
223
224static size_t readcb(char *buffer,
225              size_t size,
226              size_t nitems,
227              void *instream)
228{
229  (void)buffer;
230  (void)size;
231  (void)nitems;
232  (void)instream;
233  return 0;
234}
235
236static void errlongzero(const char *name, CURLcode code, int lineno)
237{
238  printf("%s set to 0 returned %d, \\"%s\\" on line %d\\n",
239         name, code, curl_easy_strerror(code), lineno);
240}
241
242static void errlong(const char *name, CURLcode code, int lineno)
243{
244$allowednumerrors
245  printf("%s set to non-zero returned %d, \\"%s\\" on line %d\\n",
246         name, code, curl_easy_strerror(code), lineno);
247}
248
249static void errstring(const char *name, CURLcode code, int lineno)
250{
251  /* allow this set of options to return CURLE_BAD_FUNCTION_ARGUMENT
252     when given a strange string input */
253$allowedstringerrors
254  printf("%s set to a string returned %d, \\"%s\\" on line %d\\n",
255         name, code, curl_easy_strerror(code), lineno);
256}
257
258static void err(const char *name, CURLcode val, int lineno)
259{
260  printf("%s returned %d, \\"%s\\" on line %d\\n",
261         name, val, curl_easy_strerror(val), lineno);
262}
263
264static void errnull(const char *name, CURLcode val, int lineno)
265{
266  printf("%s set to NULL returned %d, \\"%s\\" on line %d\\n",
267         name, val, curl_easy_strerror(val), lineno);
268}
269
270static void geterr(const char *name, CURLcode val, int lineno)
271{
272  printf("CURLINFO_%s returned %d, \\"%s\\" on line %d\\n",
273         name, val, curl_easy_strerror(val), lineno);
274}
275
276static curl_progress_callback progresscb;
277static curl_write_callback headercb;
278static curl_debug_callback debugcb;
279static curl_trailer_callback trailercb;
280static curl_ssl_ctx_callback ssl_ctx_cb;
281static curl_ioctl_callback ioctlcb;
282static curl_sockopt_callback sockoptcb;
283static curl_opensocket_callback opensocketcb;
284static curl_seek_callback seekcb;
285static curl_sshkeycallback ssh_keycb;
286static curl_sshhostkeycallback ssh_hostkeycb;
287static curl_chunk_bgn_callback chunk_bgn_cb;
288static curl_chunk_end_callback chunk_end_cb;
289static curl_fnmatch_callback fnmatch_cb;
290static curl_closesocket_callback closesocketcb;
291static curl_xferinfo_callback xferinfocb;
292static curl_hstsread_callback hstsreadcb;
293static curl_hstswrite_callback hstswritecb;
294static curl_resolver_start_callback resolver_start_cb;
295static curl_prereq_callback prereqcb;
296
297/* long options that are okay to return
298   CURLE_BAD_FUNCTION_ARGUMENT */
299static bool bad_long(CURLcode res, int check)
300{
301  if(res != CURLE_BAD_FUNCTION_ARGUMENT)
302    return 0; /* not okay */
303
304  if(check < CURLOPTTYPE_OBJECTPOINT) {
305    /* LONG */
306    return 1;
307  }
308  else if((check >= CURLOPTTYPE_OFF_T) &&
309          (check < CURLOPTTYPE_BLOB)) {
310    /* OFF_T */
311    return 1;
312  }
313  return 0;
314}
315
316/* macro to check the first setopt of an option which then is allowed to get a
317   non-existing function return code back */
318#define present(x) ((x != CURLE_NOT_BUILT_IN) && (x != CURLE_UNKNOWN_OPTION))
319
320CURLcode test(char *URL)
321{
322  CURL *curl = NULL;
323  CURL *dep = NULL;
324  CURLSH *share = NULL;
325  char errorbuffer[CURL_ERROR_SIZE];
326  void *conv_from_network_cb = NULL;
327  void *conv_to_network_cb = NULL;
328  void *conv_from_utf8_cb = NULL;
329  void *interleavecb = NULL;
330  char *stringpointerextra = (char *)"moooo";
331  struct curl_slist *slist = NULL;
332  struct curl_httppost *httppost = NULL;
333  curl_mime *mimepost = NULL;
334  FILE *stream = stderr;
335  struct testdata object;
336  char *charp;
337  long val;
338  curl_off_t oval;
339  double dval;
340  curl_socket_t sockfd;
341  struct curl_certinfo *certinfo;
342  struct curl_tlssessioninfo *tlssession;
343  struct curl_blob blob = { (void *)"silly", 5, 0};
344  CURLcode res = CURLE_OK;
345  (void)URL; /* not used */
346  global_init(CURL_GLOBAL_ALL);
347  easy_init(dep);
348  easy_init(curl);
349  share = curl_share_init();
350  if(!share) {
351    res = CURLE_OUT_OF_MEMORY;
352    goto test_cleanup;
353  }
354
355  CURL_IGNORE_DEPRECATION(
356HEADER
357    ;
358
359while(<STDIN>) {
360    s/^\s*(.*?)\s*$/$1/;      # Trim.
361    # Remove multi-line comment trail.
362    if($incomment) {
363        if($_ !~ /.*?\*\/\s*(.*)$/) {
364            next;
365        }
366        $_ = $1;
367        $incomment = 0;
368    }
369    if($line ne "") {
370        # Unfold line.
371        $_ = "$line $1";
372        $line = "";
373    }
374    # Remove comments.
375    while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) {
376        $_ = "$1 $2";
377    }
378    s/^\s*(.*?)\s*$/$1/;      # Trim again.
379    if($_ =~ /^(.*)\/\*/) {
380        $_ = $1;
381        $incomment = 1;
382    }
383    # Ignore preprocessor directives and blank lines.
384    if($_ =~ /^(?:#|$)/) {
385        next;
386    }
387    # Handle lines that may be continued as if they were folded.
388    if($_ !~ /[;,{}]$/) {
389        # Folded line.
390        $line = $_;
391        next;
392    }
393    if($_ =~ / CURL_DEPRECATED\(/) {
394        # Drop deprecation info.
395        if($_ !~ /^(.*?) CURL_DEPRECATED\(.*?"\)(.*)$/) {
396            # Needs unfolding.
397            $line = $_;
398            next;
399        }
400        $_ = $1 . $2;
401    }
402    if($_ =~ /^CURLOPT(?:DEPRECATED)?\(/ && $_ !~ /\),$/) {
403        # Multi-line CURLOPTs need unfolding.
404        $line = $_;
405        next;
406    }
407    if($_ =~ /^CURLOPT(?:DEPRECATED)?\(([^ ]*), ([^ ]*), (\d*)[,)]/) {
408        my ($name, $type, $val)=($1, $2, $3);
409        my $w="  ";
410        my $w2="$w$w";
411        my $w3="$w$w$w";
412        my $opt = $name;
413        $opt =~ s/^CURLOPT_//;
414        my $exists = "${w}{\n";
415        # the first check for an option
416        my $fpref = "${exists}${w2}CURLcode first =\n${w3}curl_easy_setopt(curl, $name,";
417        my $ifpresent = "${w2}if(present(first)) {\n";
418        my $pref = "${w3}res = curl_easy_setopt(curl, $name,";
419        my $i = ' ' x (length($w) + 25);
420        my $fcheck = <<MOO
421    if(first && present(first)) /* first setopt check only */
422      err("$name", first, __LINE__);
423MOO
424            ;
425        my $fstringcheck = <<MOO
426    if(first && present(first)) /* first setopt check only */
427      errstring("$name", first, __LINE__);
428MOO
429            ;
430        my $check = <<MOO
431      if(res)
432        err("$name", res, __LINE__);
433MOO
434            ;
435        my $flongcheckzero = <<MOO
436    if(first && present(first) && !bad_long(res,
437       $name))
438      errlongzero("$name", first, __LINE__);
439MOO
440            ;
441
442        my $longcheck = <<MOO
443      if(res && !bad_long(res, $name))
444        errlong("$name", res, __LINE__);
445MOO
446            ;
447
448        my $nullcheck = <<MOO
449      if(res)
450        errnull(\"$name\", res, __LINE__);
451MOO
452            ;
453
454        print "\n  /****** Verify $name ******/\n";
455        if($type eq "CURLOPTTYPE_STRINGPOINT") {
456            print "${fpref} \"string\");\n$fstringcheck";
457            print "$ifpresent";
458            print "${pref} NULL);\n$nullcheck";
459        }
460        elsif(($type eq "CURLOPTTYPE_LONG") ||
461              ($type eq "CURLOPTTYPE_VALUES")) {
462            print "${fpref} 0L);\n$flongcheckzero";
463            print "$ifpresent";
464            print "${pref} 22L);\n$longcheck";
465            print "${pref} LO);\n$longcheck";
466            print "${pref} HI);\n$longcheck";
467        }
468        elsif($type eq "CURLOPTTYPE_OFF_T") {
469            print "${fpref} OFF_NO);\n$flongcheckzero";
470            print "$ifpresent";
471            my $lvl = " " x 29;
472            print "${pref}\n${lvl}(curl_off_t)22);\n$longcheck";
473            print "${pref} OFF_HI);\n$longcheck";
474            print "${pref} OFF_LO);\n$longcheck";
475        }
476        elsif(($type eq "CURLOPTTYPE_OBJECTPOINT") ||
477              ($type eq "CURLOPTTYPE_CBPOINT")) {
478            if($name =~ /DEPENDS/) {
479              print "${fpref} dep);\n$fcheck";
480            }
481            elsif($name =~ "SHARE") {
482              print "${fpref} share);\n$fcheck";
483            }
484            elsif($name eq "CURLOPT_ERRORBUFFER") {
485              print "${fpref} errorbuffer);\n$fcheck";
486            }
487            elsif(($name eq "CURLOPT_POSTFIELDS") ||
488                  ($name eq "CURLOPT_COPYPOSTFIELDS")) {
489                # set size to zero to avoid it being "illegal"
490                print "  (void)curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);\n";
491                print "${fpref} stringpointerextra);\n$fcheck";
492            }
493            elsif($name eq "CURLOPT_HTTPPOST") {
494              print "${fpref} httppost);\n$fcheck";
495            }
496            elsif($name eq "CURLOPT_MIMEPOST") {
497              print "${fpref} mimepost);\n$fcheck";
498            }
499            elsif($name eq "CURLOPT_STDERR") {
500              print "${fpref} stream);\n$fcheck";
501            }
502            else {
503              print "${fpref} &object);\n$fcheck";
504            }
505            print "$ifpresent";
506            print "${pref} NULL);\n$nullcheck";
507        }
508        elsif($type eq "CURLOPTTYPE_SLISTPOINT") {
509            print "${fpref} slist);\n$fcheck";
510            print "$ifpresent";
511            print "${pref} NULL);\n$nullcheck";
512        }
513        elsif($type eq "CURLOPTTYPE_FUNCTIONPOINT") {
514            if($name =~ /([^ ]*)FUNCTION/) {
515                my $l=lc($1);
516                $l =~ s/^curlopt_//;
517                print "${fpref}\n$i${l}cb);\n$fcheck";
518            }
519            else {
520                print "${fpref} &func);\n$fcheck";
521            }
522            print "$ifpresent";
523            print "${pref} NULL);\n$nullcheck";
524        }
525        elsif($type eq "CURLOPTTYPE_BLOB") {
526            print "${fpref} &blob);\n$check";
527            print "$ifpresent";
528            print "${pref} NULL);\n$nullcheck";
529        }
530        else {
531            print STDERR "\nUnknown type: $type\n";
532            exit 22; # exit to make this noticed!
533        }
534
535        print <<MOO
536    } /* end of secondary checks */
537  } /* end of single setopt */
538MOO
539            ;
540    }
541    elsif($_ =~ /^CURLINFO_NONE/) {
542       $infomode = 1;
543    }
544    elsif($infomode &&
545          ($_ =~ /^CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) {
546       my ($info, $type)=($1, $2);
547       my $c = "  res = curl_easy_getinfo(curl, CURLINFO_$info,";
548       my $check = "  if(res)\n    geterr(\"$info\", res, __LINE__);\n";
549       if($type eq "STRING") {
550         print "$c &charp);\n$check";
551       }
552       elsif($type eq "LONG") {
553         print "$c &val);\n$check";
554       }
555       elsif($type eq "OFF_T") {
556         print "$c &oval);\n$check";
557       }
558       elsif($type eq "DOUBLE") {
559         print "$c &dval);\n$check";
560       }
561       elsif($type eq "SLIST") {
562         print "$c &slist);\n$check";
563         print "  if(slist)\n    curl_slist_free_all(slist);\n";
564       }
565       elsif($type eq "SOCKET") {
566         print "$c &sockfd);\n$check";
567       }
568       elsif($type eq "PTR") {
569         if($info eq "CERTINFO") {
570            print "$c &certinfo);\n$check";
571         }
572         elsif(($info eq "TLS_SESSION") ||
573               ($info eq "TLS_SSL_PTR")) {
574            print "$c &tlssession);\n$check";
575         }
576         else {
577            print STDERR "$info/$type is unsupported\n";
578         }
579       }
580       else {
581         print STDERR "$type is unsupported\n";
582       }
583    }
584}
585
586
587print <<FOOTER
588  )
589
590  curl_easy_setopt(curl, (CURLoption)1, 0);
591  res = CURLE_OK;
592test_cleanup:
593  curl_easy_cleanup(curl);
594  curl_easy_cleanup(dep);
595  curl_share_cleanup(share);
596  curl_global_cleanup();
597
598  if(!res)
599    puts("ok");
600  return res;
601}
602FOOTER
603    ;
604