Home | History | Annotate | Download | only in tests
      1 #!/usr/bin/env perl
      2 #***************************************************************************
      3 #                                  _   _ ____  _
      4 #  Project                     ___| | | |  _ \| |
      5 #                             / __| | | | |_) | |
      6 #                            | (__| |_| |  _ <| |___
      7 #                             \___|\___/|_| \_\_____|
      8 #
      9 # Copyright (C) 2016, Daniel Stenberg, <daniel (at] 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.haxx.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 ###########################################################################
     23 #
     24 # Scan symbols-in-version (which is verified to be correct by test 1119), then
     25 # verify that each option mention in there that should have its own man page
     26 # actually does.
     27 #
     28 # In addition, make sure that every current option to curl_easy_setopt,
     29 # curl_easy_getinfo and curl_multi_setopt are also mentioned in their
     30 # corresponding main (index) man page.
     31 #
     32 # src/tool_getparam.c lists all options curl can parse
     33 # docs/curl.1 documents all command line options
     34 # src/tool_help.c outputs all options with curl -h
     35 # - make sure they're all in sync
     36 #
     37 # Output all deviances to stderr.
     38 
     39 use strict;
     40 use warnings;
     41 
     42 # we may get the dir root pointed out
     43 my $root=$ARGV[0] || ".";
     44 my $syms = "$root/docs/libcurl/symbols-in-versions";
     45 my $curlh = "$root/include/curl/curl.h";
     46 my $errors=0;
     47 
     48 # the prepopulated alias list is the CURLINFO_* defines that are used for the
     49 # debug function callback and the fact that they use the same prefix as the
     50 # curl_easy_getinfo options was a mistake.
     51 my %alias = (
     52     'CURLINFO_DATA_IN' => 'none',
     53     'CURLINFO_DATA_OUT' => 'none',
     54     'CURLINFO_END' => 'none',
     55     'CURLINFO_HEADER_IN' => 'none',
     56     'CURLINFO_HEADER_OUT' => 'none',
     57     'CURLINFO_LASTONE' => 'none',
     58     'CURLINFO_NONE' => 'none',
     59     'CURLINFO_SSL_DATA_IN' => 'none',
     60     'CURLINFO_SSL_DATA_OUT' => 'none',
     61     'CURLINFO_TEXT' => 'none'
     62     );
     63 
     64 sub scanmanpage {
     65     my ($file, @words) = @_;
     66 
     67     open(M, "<$file");
     68     my @m = <M>;
     69     close(M);
     70 
     71     foreach my $m (@words) {
     72 
     73         my @g = grep(/^\.IP $m/, @m);
     74         if(!$g[0]) {
     75             print STDERR "Missing mention of $m in $file\n";
     76             $errors++;
     77         }
     78     }
     79 }
     80 
     81 # check for define alises
     82 open(R, "<$curlh") ||
     83     die "no curl.h";
     84 while(<R>) {
     85     if(/^\#define (CURL(OPT|INFO|MOPT)_\w+) (.*)/) {
     86         $alias{$1}=$3;
     87     }
     88 }
     89 close(R);
     90 
     91 my @curlopt;
     92 my @curlinfo;
     93 my @curlmopt;
     94 open(R, "<$syms") ||
     95     die "no input file";
     96 while(<R>) {
     97     chomp;
     98     my $l= $_;
     99     if($l =~ /(CURL(OPT|INFO|MOPT)_\w+) *([0-9.]*) *([0-9.-]*) *([0-9.]*)/) {
    100         my ($opt, $type, $add, $dep, $rem) = ($1, $2, $3, $4, $5);
    101 
    102         if($alias{$opt}) {
    103             #print "$opt => $alias{$opt}\n";
    104         }
    105         elsif($rem) {
    106             # $opt was removed in $rem
    107             # so don't check for that
    108         }
    109         else {
    110             if($type eq "OPT") {
    111                 push @curlopt, $opt,
    112             }
    113             elsif($type eq "INFO") {
    114                 push @curlinfo, $opt,
    115             }
    116             elsif($type eq "MOPT") {
    117                 push @curlmopt, $opt,
    118             }
    119             if(! -f "$root/docs/libcurl/opts/$opt.3") {
    120                 print STDERR "Missing $opt.3\n";
    121                 $errors++;
    122             }
    123         }
    124     }
    125 }
    126 close(R);
    127 
    128 scanmanpage("$root/docs/libcurl/curl_easy_setopt.3", @curlopt);
    129 scanmanpage("$root/docs/libcurl/curl_easy_getinfo.3", @curlinfo);
    130 scanmanpage("$root/docs/libcurl/curl_multi_setopt.3", @curlmopt);
    131 
    132 # using this hash array, we can whitelist specific options
    133 my %opts = (
    134     # pretend these --no options exists in tool_getparam.c
    135     '--no-alpn' => 1,
    136     '--no-npn' => 1,
    137     '-N, --no-buffer' => 1,
    138     '--no-sessionid' => 1,
    139     '--no-keepalive' => 1,
    140 
    141     # pretend these options without -no exist in curl.1 and tool_help.c
    142     '--alpn' => 6,
    143     '--npn' => 6,
    144     '--eprt' => 6,
    145     '--epsv' => 6,
    146     '--keepalive' => 6,
    147     '-N, --buffer' => 6,
    148     '--sessionid' => 6,
    149 
    150     # deprecated options do not need to be in curl -h output
    151     '--krb4' => 4,
    152     '--ftp-ssl' => 4,
    153     '--ftp-ssl-reqd' => 4,
    154 
    155     # for tests and debug only, can remain hidden
    156     '--test-event' => 6,
    157     '--wdebug' => 6,
    158     );
    159 
    160 
    161 #########################################################################
    162 # parse the curl code that parses the command line arguments!
    163 open(R, "<$root/src/tool_getparam.c") ||
    164     die "no input file";
    165 my $list;
    166 my @getparam; # store all parsed parameters
    167 
    168 while(<R>) {
    169     chomp;
    170     my $l= $_;
    171     if(/struct LongShort aliases/) {
    172         $list=1;
    173     }
    174     elsif($list) {
    175         if( /^  \{([^,]*), *([^ ]*)/) {
    176             my ($s, $l)=($1, $2);
    177             my $sh;
    178             my $lo;
    179             my $title;
    180             if($l =~ /\"(.*)\"/) {
    181                 # long option
    182                 $lo = $1;
    183                 $title="--$lo";
    184             }
    185             if($s =~ /\"(.)\"/) {
    186                 # a short option
    187                 $sh = $1;
    188                 $title="-$sh, $title";
    189             }
    190             push @getparam, $title;
    191             $opts{$title} |= 1;
    192         }
    193     }
    194 }
    195 close(R);
    196 
    197 #########################################################################
    198 # parse the curl.1 man page, extract all documented command line options
    199 open(R, "<$root/docs/curl.1") ||
    200     die "no input file";
    201 my @manpage; # store all parsed parameters
    202 while(<R>) {
    203     chomp;
    204     my $l= $_;
    205     if(/^\.IP \"(-[^\"]*)\"/) {
    206         my $str = $1;
    207         my $combo;
    208         if($str =~ /^-(.), --([a-z0-9.-]*)/) {
    209             # figure out the -short, --long combo
    210             $combo = "-$1, --$2";
    211         }
    212         elsif($str =~ /^--([a-z0-9.-]*)/) {
    213             # figure out the --long name
    214             $combo = "--$1";
    215         }
    216         if($combo) {
    217             push @manpage, $combo;
    218             $opts{$combo} |= 2;
    219         }
    220     }
    221 }
    222 close(R);
    223 
    224 
    225 #########################################################################
    226 # parse the curl code that outputs the curl -h list
    227 open(R, "<$root/src/tool_help.c") ||
    228     die "no input file";
    229 my @toolhelp; # store all parsed parameters
    230 while(<R>) {
    231     chomp;
    232     my $l= $_;
    233     if(/^  \" *(.*)/) {
    234         my $str=$1;
    235         my $combo;
    236         if($str =~ /^-(.), --([a-z0-9.-]*)/) {
    237             # figure out the -short, --long combo
    238             $combo = "-$1, --$2";
    239         }
    240         elsif($str =~ /^--([a-z0-9.-]*)/) {
    241             # figure out the --long name
    242             $combo = "--$1";
    243         }
    244         if($combo) {
    245             push @toolhelp, $combo;
    246             $opts{$combo} |= 4;
    247         }
    248 
    249     }
    250 }
    251 close(R);
    252 
    253 #
    254 # Now we have three arrays with options to cross-reference.
    255 
    256 foreach my $o (keys %opts) {
    257     my $where = $opts{$o};
    258 
    259     if($where != 7) {
    260         # this is not in all three places
    261         $errors++;
    262         my $exists;
    263         my $missing;
    264         if($where & 1) {
    265             $exists=" tool_getparam.c";
    266         }
    267         else {
    268             $missing=" tool_getparam.c";
    269         }
    270         if($where & 2) {
    271             $exists.= " curl.1";
    272         }
    273         else {
    274             $missing.= " curl.1";
    275         }
    276         if($where & 4) {
    277             $exists .= " tool_help.c";
    278         }
    279         else {
    280             $missing .= " tool_help.c";
    281         }
    282 
    283         print STDERR "$o is not in$missing (but in$exists)\n";
    284     }
    285 }
    286 
    287 exit $errors;
    288