xref: /curl/tests/libtest/mk-lib1521.pl (revision 0e18bd39)
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
174if(!$ARGV[0]) {
175    die "missing target file name";
176}
177
178use File::Temp qw/ :mktemp  /;
179
180my ($fh, $tempfile) = mkstemp("lib1521-XXXXX");
181
182print $fh <<HEADER
183/***************************************************************************
184 *                                  _   _ ____  _
185 *  Project                     ___| | | |  _ \\| |
186 *                             / __| | | | |_) | |
187 *                            | (__| |_| |  _ <| |___
188 *                             \\___|\\___/|_| \\_\\_____|
189 *
190 * Copyright (C) Daniel Stenberg, <daniel\@haxx.se>, et al.
191 *
192 * This software is licensed as described in the file COPYING, which
193 * you should have received as part of this distribution. The terms
194 * are also available at https://curl.se/docs/copyright.html.
195 *
196 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
197 * copies of the Software, and permit persons to whom the Software is
198 * furnished to do so, under the terms of the COPYING file.
199 *
200 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
201 * KIND, either express or implied.
202 *
203 * SPDX-License-Identifier: curl
204 *
205 ***************************************************************************/
206#include "test.h"
207#include "memdebug.h"
208#include <limits.h>
209
210/* This source code is generated by mk-lib1521.pl ! */
211
212struct testdata {
213    char *blaha;
214};
215
216#define LO $minlong
217#define HI $maxlong
218#define OFF_LO (curl_off_t) LO
219#define OFF_HI (curl_off_t) $maxofft
220#define OFF_NO (curl_off_t) 0
221
222static size_t writecb(char *buffer, size_t size, size_t nitems,
223                      void *outstream)
224{
225  (void)buffer;
226  (void)size;
227  (void)nitems;
228  (void)outstream;
229  return 0;
230}
231
232static size_t readcb(char *buffer,
233              size_t size,
234              size_t nitems,
235              void *instream)
236{
237  (void)buffer;
238  (void)size;
239  (void)nitems;
240  (void)instream;
241  return 0;
242}
243
244static void errlongzero(const char *name, CURLcode code, int lineno)
245{
246  printf("%s set to 0 returned %d, \\"%s\\" on line %d\\n",
247         name, code, curl_easy_strerror(code), lineno);
248}
249
250static void errlong(const char *name, CURLcode code, int lineno)
251{
252$allowednumerrors
253  printf("%s set to non-zero returned %d, \\"%s\\" on line %d\\n",
254         name, code, curl_easy_strerror(code), lineno);
255}
256
257static void errstring(const char *name, CURLcode code, int lineno)
258{
259  /* allow this set of options to return CURLE_BAD_FUNCTION_ARGUMENT
260     when given a strange string input */
261$allowedstringerrors
262  printf("%s set to a string returned %d, \\"%s\\" on line %d\\n",
263         name, code, curl_easy_strerror(code), lineno);
264}
265
266static void err(const char *name, CURLcode val, int lineno)
267{
268  printf("%s returned %d, \\"%s\\" on line %d\\n",
269         name, val, curl_easy_strerror(val), lineno);
270}
271
272static void errnull(const char *name, CURLcode val, int lineno)
273{
274  printf("%s set to NULL returned %d, \\"%s\\" on line %d\\n",
275         name, val, curl_easy_strerror(val), lineno);
276}
277
278static void geterr(const char *name, CURLcode val, int lineno)
279{
280  printf("CURLINFO_%s returned %d, \\"%s\\" on line %d\\n",
281         name, val, curl_easy_strerror(val), lineno);
282}
283
284static curl_progress_callback progresscb;
285static curl_write_callback headercb;
286static curl_debug_callback debugcb;
287static curl_trailer_callback trailercb;
288static curl_ssl_ctx_callback ssl_ctx_cb;
289static curl_ioctl_callback ioctlcb;
290static curl_sockopt_callback sockoptcb;
291static curl_opensocket_callback opensocketcb;
292static curl_seek_callback seekcb;
293static curl_sshkeycallback ssh_keycb;
294static curl_sshhostkeycallback ssh_hostkeycb;
295static curl_chunk_bgn_callback chunk_bgn_cb;
296static curl_chunk_end_callback chunk_end_cb;
297static curl_fnmatch_callback fnmatch_cb;
298static curl_closesocket_callback closesocketcb;
299static curl_xferinfo_callback xferinfocb;
300static curl_hstsread_callback hstsreadcb;
301static curl_hstswrite_callback hstswritecb;
302static curl_resolver_start_callback resolver_start_cb;
303static curl_prereq_callback prereqcb;
304
305/* long options that are okay to return
306   CURLE_BAD_FUNCTION_ARGUMENT */
307static bool bad_long(CURLcode res, int check)
308{
309  if(res != CURLE_BAD_FUNCTION_ARGUMENT)
310    return 0; /* not okay */
311
312  if(check < CURLOPTTYPE_OBJECTPOINT) {
313    /* LONG */
314    return 1;
315  }
316  else if((check >= CURLOPTTYPE_OFF_T) &&
317          (check < CURLOPTTYPE_BLOB)) {
318    /* OFF_T */
319    return 1;
320  }
321  return 0;
322}
323
324/* macro to check the first setopt of an option which then is allowed to get a
325   non-existing function return code back */
326#define present(x) ((x != CURLE_NOT_BUILT_IN) && (x != CURLE_UNKNOWN_OPTION))
327
328CURLcode test(char *URL)
329{
330  CURL *curl = NULL;
331  CURL *dep = NULL;
332  CURLSH *share = NULL;
333  char errorbuffer[CURL_ERROR_SIZE];
334  void *conv_from_network_cb = NULL;
335  void *conv_to_network_cb = NULL;
336  void *conv_from_utf8_cb = NULL;
337  void *interleavecb = NULL;
338  char *stringpointerextra = (char *)"moooo";
339  struct curl_slist *slist = NULL;
340  struct curl_httppost *httppost = NULL;
341  curl_mime *mimepost = NULL;
342  FILE *stream = stderr;
343  struct testdata object;
344  char *charp;
345  long val;
346  curl_off_t oval;
347  double dval;
348  curl_socket_t sockfd;
349  struct curl_certinfo *certinfo;
350  struct curl_tlssessioninfo *tlssession;
351  struct curl_blob blob = { (void *)"silly", 5, 0};
352  CURLcode res = CURLE_OK;
353  (void)URL; /* not used */
354  global_init(CURL_GLOBAL_ALL);
355  easy_init(dep);
356  easy_init(curl);
357  share = curl_share_init();
358  if(!share) {
359    res = CURLE_OUT_OF_MEMORY;
360    goto test_cleanup;
361  }
362
363  CURL_IGNORE_DEPRECATION(
364HEADER
365    ;
366
367while(<STDIN>) {
368    s/^\s*(.*?)\s*$/$1/;      # Trim.
369    # Remove multi-line comment trail.
370    if($incomment) {
371        if($_ !~ /.*?\*\/\s*(.*)$/) {
372            next;
373        }
374        $_ = $1;
375        $incomment = 0;
376    }
377    if($line ne "") {
378        # Unfold line.
379        $_ = "$line $1";
380        $line = "";
381    }
382    # Remove comments.
383    while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) {
384        $_ = "$1 $2";
385    }
386    s/^\s*(.*?)\s*$/$1/;      # Trim again.
387    if($_ =~ /^(.*)\/\*/) {
388        $_ = $1;
389        $incomment = 1;
390    }
391    # Ignore preprocessor directives and blank lines.
392    if($_ =~ /^(?:#|$)/) {
393        next;
394    }
395    # Handle lines that may be continued as if they were folded.
396    if($_ !~ /[;,{}]$/) {
397        # Folded line.
398        $line = $_;
399        next;
400    }
401    if($_ =~ / CURL_DEPRECATED\(/) {
402        # Drop deprecation info.
403        if($_ !~ /^(.*?) CURL_DEPRECATED\(.*?"\)(.*)$/) {
404            # Needs unfolding.
405            $line = $_;
406            next;
407        }
408        $_ = $1 . $2;
409    }
410    if($_ =~ /^CURLOPT(?:DEPRECATED)?\(/ && $_ !~ /\),$/) {
411        # Multi-line CURLOPTs need unfolding.
412        $line = $_;
413        next;
414    }
415    if($_ =~ /^CURLOPT(?:DEPRECATED)?\(([^ ]*), ([^ ]*), (\d*)[,)]/) {
416        my ($name, $type, $val)=($1, $2, $3);
417        my $w="  ";
418        my $w2="$w$w";
419        my $w3="$w$w$w";
420        my $opt = $name;
421        $opt =~ s/^CURLOPT_//;
422        my $exists = "${w}{\n";
423        # the first check for an option
424        my $fpref = "${exists}${w2}CURLcode first =\n${w3}curl_easy_setopt(curl, $name,";
425        my $ifpresent = "${w2}if(present(first)) {\n";
426        my $pref = "${w3}res = curl_easy_setopt(curl, $name,";
427        my $i = ' ' x (length($w) + 25);
428        my $fcheck = <<MOO
429    if(first && present(first)) /* first setopt check only */
430      err("$name", first, __LINE__);
431MOO
432            ;
433        my $fstringcheck = <<MOO
434    if(first && present(first)) /* first setopt check only */
435      errstring("$name", first, __LINE__);
436MOO
437            ;
438        my $check = <<MOO
439      if(res)
440        err("$name", res, __LINE__);
441MOO
442            ;
443        my $flongcheckzero = <<MOO
444    if(first && present(first) && !bad_long(first,
445       $name))
446      errlongzero("$name", first, __LINE__);
447MOO
448            ;
449
450        my $longcheck = <<MOO
451      if(res && !bad_long(res, $name))
452        errlong("$name", res, __LINE__);
453MOO
454            ;
455
456        my $nullcheck = <<MOO
457      if(res)
458        errnull(\"$name\", res, __LINE__);
459MOO
460            ;
461
462        print $fh "\n  /****** Verify $name ******/\n";
463        if($type eq "CURLOPTTYPE_STRINGPOINT") {
464            print $fh "${fpref} \"string\");\n$fstringcheck";
465            print $fh "$ifpresent";
466            print $fh "${pref} NULL);\n$nullcheck";
467        }
468        elsif(($type eq "CURLOPTTYPE_LONG") ||
469              ($type eq "CURLOPTTYPE_VALUES")) {
470            print $fh "${fpref} 0L);\n$flongcheckzero";
471            print $fh "$ifpresent";
472            print $fh "${pref} 22L);\n$longcheck";
473            print $fh "${pref} LO);\n$longcheck";
474            print $fh "${pref} HI);\n$longcheck";
475        }
476        elsif($type eq "CURLOPTTYPE_OFF_T") {
477            print $fh "${fpref} OFF_NO);\n$flongcheckzero";
478            print $fh "$ifpresent";
479            my $lvl = " " x 29;
480            print $fh "${pref}\n${lvl}(curl_off_t)22);\n$longcheck";
481            print $fh "${pref} OFF_HI);\n$longcheck";
482            print $fh "${pref} OFF_LO);\n$longcheck";
483        }
484        elsif(($type eq "CURLOPTTYPE_OBJECTPOINT") ||
485              ($type eq "CURLOPTTYPE_CBPOINT")) {
486            if($name =~ /DEPENDS/) {
487              print $fh "${fpref} dep);\n$fcheck";
488            }
489            elsif($name =~ "SHARE") {
490              print $fh "${fpref} share);\n$fcheck";
491            }
492            elsif($name eq "CURLOPT_ERRORBUFFER") {
493              print $fh "${fpref} errorbuffer);\n$fcheck";
494            }
495            elsif(($name eq "CURLOPT_POSTFIELDS") ||
496                  ($name eq "CURLOPT_COPYPOSTFIELDS")) {
497                # set size to zero to avoid it being "illegal"
498                print $fh "  (void)curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);\n";
499                print $fh "${fpref} stringpointerextra);\n$fcheck";
500            }
501            elsif($name eq "CURLOPT_HTTPPOST") {
502              print $fh "${fpref} httppost);\n$fcheck";
503            }
504            elsif($name eq "CURLOPT_MIMEPOST") {
505              print $fh "${fpref} mimepost);\n$fcheck";
506            }
507            elsif($name eq "CURLOPT_STDERR") {
508              print $fh "${fpref} stream);\n$fcheck";
509            }
510            else {
511              print $fh "${fpref} &object);\n$fcheck";
512            }
513            print $fh "$ifpresent";
514            print $fh "${pref} NULL);\n$nullcheck";
515        }
516        elsif($type eq "CURLOPTTYPE_SLISTPOINT") {
517            print $fh "${fpref} slist);\n$fcheck";
518            print $fh "$ifpresent";
519            print $fh "${pref} NULL);\n$nullcheck";
520        }
521        elsif($type eq "CURLOPTTYPE_FUNCTIONPOINT") {
522            if($name =~ /([^ ]*)FUNCTION/) {
523                my $l=lc($1);
524                $l =~ s/^curlopt_//;
525                print $fh "${fpref}\n$i${l}cb);\n$fcheck";
526            }
527            else {
528                print $fh "${fpref} &func);\n$fcheck";
529            }
530            print $fh "$ifpresent";
531            print $fh "${pref} NULL);\n$nullcheck";
532        }
533        elsif($type eq "CURLOPTTYPE_BLOB") {
534            print $fh "${fpref} &blob);\n$check";
535            print $fh "$ifpresent";
536            print $fh "${pref} NULL);\n$nullcheck";
537        }
538        else {
539            print STDERR "\nUnknown type: $type\n";
540            exit 22; # exit to make this noticed!
541        }
542
543        print $fh <<MOO
544    } /* end of secondary checks */
545  } /* end of single setopt */
546MOO
547            ;
548    }
549    elsif($_ =~ /^CURLINFO_NONE/) {
550       $infomode = 1;
551    }
552    elsif($infomode &&
553          ($_ =~ /^CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) {
554       my ($info, $type)=($1, $2);
555       my $c = "  res = curl_easy_getinfo(curl, CURLINFO_$info,";
556       my $check = "  if(res)\n    geterr(\"$info\", res, __LINE__);\n";
557       if($type eq "STRING") {
558         print $fh "$c &charp);\n$check";
559       }
560       elsif($type eq "LONG") {
561         print $fh "$c &val);\n$check";
562       }
563       elsif($type eq "OFF_T") {
564         print $fh "$c &oval);\n$check";
565       }
566       elsif($type eq "DOUBLE") {
567         print $fh "$c &dval);\n$check";
568       }
569       elsif($type eq "SLIST") {
570         print $fh "$c &slist);\n$check";
571         print $fh "  if(slist)\n    curl_slist_free_all(slist);\n";
572       }
573       elsif($type eq "SOCKET") {
574         print $fh "$c &sockfd);\n$check";
575       }
576       elsif($type eq "PTR") {
577         if($info eq "CERTINFO") {
578            print $fh "$c &certinfo);\n$check";
579         }
580         elsif(($info eq "TLS_SESSION") ||
581               ($info eq "TLS_SSL_PTR")) {
582            print $fh "$c &tlssession);\n$check";
583         }
584         else {
585            print STDERR "$info/$type is unsupported\n";
586         }
587       }
588       else {
589         print STDERR "$type is unsupported\n";
590       }
591    }
592}
593
594
595print $fh <<FOOTER
596  )
597  curl_easy_setopt(curl, (CURLoption)1, 0);
598  res = CURLE_OK;
599test_cleanup:
600  curl_easy_cleanup(curl);
601  curl_easy_cleanup(dep);
602  curl_share_cleanup(share);
603  curl_global_cleanup();
604
605  if(!res)
606    puts("ok");
607  return res;
608}
609FOOTER
610    ;
611
612close($fh);
613rename($tempfile, $ARGV[0]);
614