xref: /curl/tests/test1139.pl (revision 82c53f82)
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-event' => 6,
184    '--wdebug' => 6,
185    );
186
187
188#########################################################################
189# parse the curl code that parses the command line arguments!
190open($r, "<", "$root/src/tool_getparam.c") ||
191    die "no input file";
192my $list;
193my @getparam; # store all parsed parameters
194
195my $prevlong = "";
196my $no = 0;
197while(<$r>) {
198    $no++;
199    chomp;
200    if(/struct LongShort aliases/) {
201        $list=1;
202    }
203    elsif($list) {
204        if( /^  \{(\"[^,]*\").*\'(.)\', (.*)\}/) {
205            my ($l, $s, $rd)=($1, $2, $3);
206            my $sh;
207            my $lo;
208            my $title;
209            if(($l cmp $prevlong) < 0) {
210                print STDERR "tool_getparam.c:$no: '$l' is NOT placed in alpha-order\n";
211            }
212            if($l =~ /\"(.*)\"/) {
213                # long option
214                $lo = $1;
215                $title="--$lo";
216            }
217            if($s ne " ") {
218                # a short option
219                $sh = $s;
220                $title="-$sh, $title";
221            }
222            push @getparam, $title;
223            $opts{$title} |= 1;
224            $prevlong = $l;
225        }
226    }
227}
228close($r);
229
230#########################################################################
231# parse the curl.1 manpage, extract all documented command line options
232# The manpage may or may not be rebuilt, so check both possible locations
233open($r, "<", "$buildroot/docs/cmdline-opts/curl.1") || open($r, "<", "$root/docs/cmdline-opts/curl.1") ||
234    die "failed getting curl.1";
235my @manpage; # store all parsed parameters
236while(<$r>) {
237    chomp;
238    my $l= $_;
239    $l =~ s/\\-/-/g;
240    if($l =~ /^\.IP \"(-[^\"]*)\"/) {
241        my $str = $1;
242        my $combo;
243        if($str =~ /^-(.), --([a-z0-9.-]*)/) {
244            # figure out the -short, --long combo
245            $combo = "-$1, --$2";
246        }
247        elsif($str =~ /^--([a-z0-9.-]*)/) {
248            # figure out the --long name
249            $combo = "--$1";
250        }
251        if($combo) {
252            push @manpage, $combo;
253            $opts{$combo} |= 2;
254        }
255    }
256}
257close($r);
258
259
260#########################################################################
261# parse the curl code that outputs the curl -h list
262open($r, "<", "$root/src/tool_listhelp.c") ||
263    die "no input file";
264my @toolhelp; # store all parsed parameters
265while(<$r>) {
266    chomp;
267    my $l= $_;
268    if(/^  \{\" *(.*)/) {
269        my $str=$1;
270        my $combo;
271        if($str =~ /^-(.), --([a-z0-9.-]*)/) {
272            # figure out the -short, --long combo
273            $combo = "-$1, --$2";
274        }
275        elsif($str =~ /^--([a-z0-9.-]*)/) {
276            # figure out the --long name
277            $combo = "--$1";
278        }
279        if($combo) {
280            push @toolhelp, $combo;
281            $opts{$combo} |= 4;
282        }
283
284    }
285}
286close($r);
287
288#
289# Now we have three arrays with options to cross-reference.
290
291foreach my $o (keys %opts) {
292    my $where = $opts{$o};
293
294    if($where != 7) {
295        # this is not in all three places
296        $errors++;
297        my $exists;
298        my $missing;
299        if($where & 1) {
300            $exists=" tool_getparam.c";
301        }
302        else {
303            $missing=" tool_getparam.c";
304        }
305        if($where & 2) {
306            $exists.= " curl.1";
307        }
308        else {
309            $missing.= " curl.1";
310        }
311        if($where & 4) {
312            $exists .= " tool_listhelp.c";
313        }
314        else {
315            $missing .= " tool_listhelp.c";
316        }
317
318        print STDERR "$o is not in$missing (but in$exists)\n";
319    }
320}
321
322print STDERR "$errors\n";
323