xref: /curl/tests/test1139.pl (revision f03c8563)
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 man page
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) man page.
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 scanmanpage {
68    my ($file, @words) = @_;
69
70    open(my $mh, "<", "$file") ||
71        die "could not open $file";
72    my @m;
73    while(<$mh>) {
74        if($_ =~ /^\.IP (.*)/) {
75            my $w = $1;
76            # "unquote" minuses
77            $w =~ s/\\-/-/g;
78            push @m, $w;
79        }
80    }
81    close($mh);
82
83    foreach my $m (@words) {
84        my @g = grep(/$m/, @m);
85        if(!$g[0]) {
86            print STDERR "Missing mention of $m in $file\n";
87            $errors++;
88        }
89    }
90}
91
92my $r;
93
94# check for define aliases
95open($r, "<", "$curlh") ||
96    die "no curl.h";
97while(<$r>) {
98    if(/^\#define (CURL(OPT|INFO|MOPT)_\w+) (.*)/) {
99        $alias{$1}=$3;
100    }
101}
102close($r);
103
104my @curlopt;
105my @curlinfo;
106my @curlmopt;
107open($r, "<", "$syms") ||
108    die "no input file";
109while(<$r>) {
110    chomp;
111    my $l= $_;
112    if($l =~ /(CURL(OPT|INFO|MOPT)_\w+) *([0-9.]*) *([0-9.-]*) *([0-9.]*)/) {
113        my ($opt, $type, $add, $dep, $rem) = ($1, $2, $3, $4, $5);
114
115        if($alias{$opt}) {
116            #print "$opt => $alias{$opt}\n";
117        }
118        elsif($rem) {
119            # $opt was removed in $rem
120            # so don't check for that
121        }
122        else {
123            if($type eq "OPT") {
124                push @curlopt, $opt,
125            }
126            elsif($type eq "INFO") {
127                push @curlinfo, $opt,
128            }
129            elsif($type eq "MOPT") {
130                push @curlmopt, $opt,
131            }
132            if(! -f "$buildroot/docs/libcurl/opts/$opt.3") {
133                print STDERR "Missing $opt.3\n";
134                $errors++;
135            }
136        }
137    }
138}
139close($r);
140
141scanmanpage("$buildroot/docs/libcurl/curl_easy_setopt.3", @curlopt);
142scanmanpage("$buildroot/docs/libcurl/curl_easy_getinfo.3", @curlinfo);
143scanmanpage("$buildroot/docs/libcurl/curl_multi_setopt.3", @curlmopt);
144
145# using this hash array, we can skip specific options
146my %opts = (
147    # pretend these --no options exists in tool_getparam.c
148    '--no-alpn' => 1,
149    '--no-npn' => 1,
150    '-N, --no-buffer' => 1,
151    '--no-sessionid' => 1,
152    '--no-keepalive' => 1,
153    '--no-progress-meter' => 1,
154    '--no-clobber' => 1,
155
156    # pretend these options without -no exist in curl.1 and tool_listhelp.c
157    '--alpn' => 6,
158    '--npn' => 6,
159    '--eprt' => 6,
160    '--epsv' => 6,
161    '--keepalive' => 6,
162    '-N, --buffer' => 6,
163    '--sessionid' => 6,
164    '--progress-meter' => 6,
165    '--clobber' => 6,
166
167    # deprecated options do not need to be in tool_help.c nor curl.1
168    '--krb4' => 6,
169    '--ftp-ssl' => 6,
170    '--ftp-ssl-reqd' => 6,
171
172    # for tests and debug only, can remain hidden
173    '--test-event' => 6,
174    '--wdebug' => 6,
175    );
176
177
178#########################################################################
179# parse the curl code that parses the command line arguments!
180open($r, "<", "$root/src/tool_getparam.c") ||
181    die "no input file";
182my $list;
183my @getparam; # store all parsed parameters
184
185my $prevlong = "";
186my $no = 0;
187while(<$r>) {
188    $no++;
189    chomp;
190    if(/struct LongShort aliases/) {
191        $list=1;
192    }
193    elsif($list) {
194        if( /^  \{(\"[^,]*\").*\'(.)\', (.*)\}/) {
195            my ($l, $s, $rd)=($1, $2, $3);
196            my $sh;
197            my $lo;
198            my $title;
199            if(($l cmp $prevlong) < 0) {
200                print STDERR "tool_getparam.c:$no: '$l' is NOT placed in alpha-order\n";
201            }
202            if($l =~ /\"(.*)\"/) {
203                # long option
204                $lo = $1;
205                $title="--$lo";
206            }
207            if($s ne " ") {
208                # a short option
209                $sh = $s;
210                $title="-$sh, $title";
211            }
212            push @getparam, $title;
213            $opts{$title} |= 1;
214            $prevlong = $l;
215        }
216    }
217}
218close($r);
219
220#########################################################################
221# parse the curl.1 man page, extract all documented command line options
222# The man page may or may not be rebuilt, so check both possible locations
223open($r, "<", "$buildroot/docs/cmdline-opts/curl.1") || open($r, "<", "$root/docs/cmdline-opts/curl.1") ||
224    die "failed getting curl.1";
225my @manpage; # store all parsed parameters
226while(<$r>) {
227    chomp;
228    my $l= $_;
229    $l =~ s/\\-/-/g;
230    if($l =~ /^\.IP \"(-[^\"]*)\"/) {
231        my $str = $1;
232        my $combo;
233        if($str =~ /^-(.), --([a-z0-9.-]*)/) {
234            # figure out the -short, --long combo
235            $combo = "-$1, --$2";
236        }
237        elsif($str =~ /^--([a-z0-9.-]*)/) {
238            # figure out the --long name
239            $combo = "--$1";
240        }
241        if($combo) {
242            push @manpage, $combo;
243            $opts{$combo} |= 2;
244        }
245    }
246}
247close($r);
248
249
250#########################################################################
251# parse the curl code that outputs the curl -h list
252open($r, "<", "$root/src/tool_listhelp.c") ||
253    die "no input file";
254my @toolhelp; # store all parsed parameters
255while(<$r>) {
256    chomp;
257    my $l= $_;
258    if(/^  \{\" *(.*)/) {
259        my $str=$1;
260        my $combo;
261        if($str =~ /^-(.), --([a-z0-9.-]*)/) {
262            # figure out the -short, --long combo
263            $combo = "-$1, --$2";
264        }
265        elsif($str =~ /^--([a-z0-9.-]*)/) {
266            # figure out the --long name
267            $combo = "--$1";
268        }
269        if($combo) {
270            push @toolhelp, $combo;
271            $opts{$combo} |= 4;
272        }
273
274    }
275}
276close($r);
277
278#
279# Now we have three arrays with options to cross-reference.
280
281foreach my $o (keys %opts) {
282    my $where = $opts{$o};
283
284    if($where != 7) {
285        # this is not in all three places
286        $errors++;
287        my $exists;
288        my $missing;
289        if($where & 1) {
290            $exists=" tool_getparam.c";
291        }
292        else {
293            $missing=" tool_getparam.c";
294        }
295        if($where & 2) {
296            $exists.= " curl.1";
297        }
298        else {
299            $missing.= " curl.1";
300        }
301        if($where & 4) {
302            $exists .= " tool_listhelp.c";
303        }
304        else {
305            $missing .= " tool_listhelp.c";
306        }
307
308        print STDERR "$o is not in$missing (but in$exists)\n";
309    }
310}
311
312print STDERR "$errors\n";
313