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