xref: /aosp_15_r20/external/curl/tests/testutil.pm (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker#***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker#                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker#  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker#                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker#                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker#                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker#
8*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker#
10*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker#
14*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker#
18*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker#
21*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker#
23*6236dae4SAndroid Build Coastguard Worker###########################################################################
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker# This module contains miscellaneous functions needed in several parts of
26*6236dae4SAndroid Build Coastguard Worker# the test suite.
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard Workerpackage testutil;
29*6236dae4SAndroid Build Coastguard Worker
30*6236dae4SAndroid Build Coastguard Workeruse strict;
31*6236dae4SAndroid Build Coastguard Workeruse warnings;
32*6236dae4SAndroid Build Coastguard Worker
33*6236dae4SAndroid Build Coastguard WorkerBEGIN {
34*6236dae4SAndroid Build Coastguard Worker    use base qw(Exporter);
35*6236dae4SAndroid Build Coastguard Worker
36*6236dae4SAndroid Build Coastguard Worker    our @EXPORT = qw(
37*6236dae4SAndroid Build Coastguard Worker        runclient
38*6236dae4SAndroid Build Coastguard Worker        runclientoutput
39*6236dae4SAndroid Build Coastguard Worker        setlogfunc
40*6236dae4SAndroid Build Coastguard Worker        shell_quote
41*6236dae4SAndroid Build Coastguard Worker        subbase64
42*6236dae4SAndroid Build Coastguard Worker        subnewlines
43*6236dae4SAndroid Build Coastguard Worker        subsha256base64file
44*6236dae4SAndroid Build Coastguard Worker        substrippemfile
45*6236dae4SAndroid Build Coastguard Worker    );
46*6236dae4SAndroid Build Coastguard Worker
47*6236dae4SAndroid Build Coastguard Worker    our @EXPORT_OK = qw(
48*6236dae4SAndroid Build Coastguard Worker        clearlogs
49*6236dae4SAndroid Build Coastguard Worker        logmsg
50*6236dae4SAndroid Build Coastguard Worker    );
51*6236dae4SAndroid Build Coastguard Worker}
52*6236dae4SAndroid Build Coastguard Worker
53*6236dae4SAndroid Build Coastguard Workeruse Digest::SHA qw(sha256);
54*6236dae4SAndroid Build Coastguard Workeruse MIME::Base64;
55*6236dae4SAndroid Build Coastguard Worker
56*6236dae4SAndroid Build Coastguard Workeruse globalconfig qw(
57*6236dae4SAndroid Build Coastguard Worker    $torture
58*6236dae4SAndroid Build Coastguard Worker    $verbose
59*6236dae4SAndroid Build Coastguard Worker    $dev_null
60*6236dae4SAndroid Build Coastguard Worker);
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard Workermy $logfunc;      # optional reference to function for logging
63*6236dae4SAndroid Build Coastguard Workermy @logmessages;  # array holding logged messages
64*6236dae4SAndroid Build Coastguard Worker
65*6236dae4SAndroid Build Coastguard Worker
66*6236dae4SAndroid Build Coastguard Worker#######################################################################
67*6236dae4SAndroid Build Coastguard Worker# Log an informational message
68*6236dae4SAndroid Build Coastguard Worker# If a log callback function was set in setlogfunc, it is called. If not,
69*6236dae4SAndroid Build Coastguard Worker# then the log message is buffered until retrieved by clearlogs.
70*6236dae4SAndroid Build Coastguard Worker#
71*6236dae4SAndroid Build Coastguard Worker# logmsg must only be called by one of the runner_* entry points and functions
72*6236dae4SAndroid Build Coastguard Worker# called by them, or else logs risk being lost, since those are the only
73*6236dae4SAndroid Build Coastguard Worker# functions that know about and will return buffered logs.
74*6236dae4SAndroid Build Coastguard Workersub logmsg {
75*6236dae4SAndroid Build Coastguard Worker    if(!scalar(@_)) {
76*6236dae4SAndroid Build Coastguard Worker        return;
77*6236dae4SAndroid Build Coastguard Worker    }
78*6236dae4SAndroid Build Coastguard Worker    if(defined $logfunc) {
79*6236dae4SAndroid Build Coastguard Worker        &$logfunc(@_);
80*6236dae4SAndroid Build Coastguard Worker        return;
81*6236dae4SAndroid Build Coastguard Worker    }
82*6236dae4SAndroid Build Coastguard Worker    push @logmessages, @_;
83*6236dae4SAndroid Build Coastguard Worker}
84*6236dae4SAndroid Build Coastguard Worker
85*6236dae4SAndroid Build Coastguard Worker#######################################################################
86*6236dae4SAndroid Build Coastguard Worker# Set the function to use for logging
87*6236dae4SAndroid Build Coastguard Workersub setlogfunc {
88*6236dae4SAndroid Build Coastguard Worker    ($logfunc)=@_;
89*6236dae4SAndroid Build Coastguard Worker}
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker#######################################################################
92*6236dae4SAndroid Build Coastguard Worker# Clear the buffered log messages after returning them
93*6236dae4SAndroid Build Coastguard Workersub clearlogs {
94*6236dae4SAndroid Build Coastguard Worker    my $loglines = join('', @logmessages);
95*6236dae4SAndroid Build Coastguard Worker    undef @logmessages;
96*6236dae4SAndroid Build Coastguard Worker    return $loglines;
97*6236dae4SAndroid Build Coastguard Worker}
98*6236dae4SAndroid Build Coastguard Worker
99*6236dae4SAndroid Build Coastguard Worker
100*6236dae4SAndroid Build Coastguard Worker#######################################################################
101*6236dae4SAndroid Build Coastguard Worker
102*6236dae4SAndroid Build Coastguard Workersub includefile {
103*6236dae4SAndroid Build Coastguard Worker    my ($f) = @_;
104*6236dae4SAndroid Build Coastguard Worker    open(F, "<$f");
105*6236dae4SAndroid Build Coastguard Worker    my @a = <F>;
106*6236dae4SAndroid Build Coastguard Worker    close(F);
107*6236dae4SAndroid Build Coastguard Worker    return join("", @a);
108*6236dae4SAndroid Build Coastguard Worker}
109*6236dae4SAndroid Build Coastguard Worker
110*6236dae4SAndroid Build Coastguard Workersub subbase64 {
111*6236dae4SAndroid Build Coastguard Worker    my ($thing) = @_;
112*6236dae4SAndroid Build Coastguard Worker
113*6236dae4SAndroid Build Coastguard Worker    # cut out the base64 piece
114*6236dae4SAndroid Build Coastguard Worker    while($$thing =~ s/%b64\[(.*?)\]b64%/%%B64%%/i) {
115*6236dae4SAndroid Build Coastguard Worker        my $d = $1;
116*6236dae4SAndroid Build Coastguard Worker        # encode %NN characters
117*6236dae4SAndroid Build Coastguard Worker        $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
118*6236dae4SAndroid Build Coastguard Worker        my $enc = encode_base64($d, "");
119*6236dae4SAndroid Build Coastguard Worker        # put the result into there
120*6236dae4SAndroid Build Coastguard Worker        $$thing =~ s/%%B64%%/$enc/;
121*6236dae4SAndroid Build Coastguard Worker    }
122*6236dae4SAndroid Build Coastguard Worker    # hex decode
123*6236dae4SAndroid Build Coastguard Worker    while($$thing =~ s/%hex\[(.*?)\]hex%/%%HEX%%/i) {
124*6236dae4SAndroid Build Coastguard Worker        # decode %NN characters
125*6236dae4SAndroid Build Coastguard Worker        my $d = $1;
126*6236dae4SAndroid Build Coastguard Worker        $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
127*6236dae4SAndroid Build Coastguard Worker        $$thing =~ s/%%HEX%%/$d/;
128*6236dae4SAndroid Build Coastguard Worker    }
129*6236dae4SAndroid Build Coastguard Worker    # repeat
130*6236dae4SAndroid Build Coastguard Worker    while($$thing =~ s/%repeat\[(\d+) x (.*?)\]%/%%REPEAT%%/i) {
131*6236dae4SAndroid Build Coastguard Worker        # decode %NN characters
132*6236dae4SAndroid Build Coastguard Worker        my ($d, $n) = ($2, $1);
133*6236dae4SAndroid Build Coastguard Worker        $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
134*6236dae4SAndroid Build Coastguard Worker        $n =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
135*6236dae4SAndroid Build Coastguard Worker        my $all = $d x $n;
136*6236dae4SAndroid Build Coastguard Worker        $$thing =~ s/%%REPEAT%%/$all/;
137*6236dae4SAndroid Build Coastguard Worker    }
138*6236dae4SAndroid Build Coastguard Worker
139*6236dae4SAndroid Build Coastguard Worker    # include a file
140*6236dae4SAndroid Build Coastguard Worker    $$thing =~ s/%include ([^%]*)%[\n\r]+/includefile($1)/ge;
141*6236dae4SAndroid Build Coastguard Worker}
142*6236dae4SAndroid Build Coastguard Worker
143*6236dae4SAndroid Build Coastguard Workermy $prevupdate;  # module scope so it remembers the last value
144*6236dae4SAndroid Build Coastguard Workersub subnewlines {
145*6236dae4SAndroid Build Coastguard Worker    my ($force, $thing) = @_;
146*6236dae4SAndroid Build Coastguard Worker
147*6236dae4SAndroid Build Coastguard Worker    if($force) {
148*6236dae4SAndroid Build Coastguard Worker        # enforce CRLF newline
149*6236dae4SAndroid Build Coastguard Worker        $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
150*6236dae4SAndroid Build Coastguard Worker        return;
151*6236dae4SAndroid Build Coastguard Worker    }
152*6236dae4SAndroid Build Coastguard Worker
153*6236dae4SAndroid Build Coastguard Worker    # When curl is built with Hyper, it gets all response headers delivered as
154*6236dae4SAndroid Build Coastguard Worker    # name/value pairs and curl "invents" the newlines when it saves the
155*6236dae4SAndroid Build Coastguard Worker    # headers. Therefore, curl will always save headers with CRLF newlines
156*6236dae4SAndroid Build Coastguard Worker    # when built to use Hyper. By making sure we deliver all tests using CRLF
157*6236dae4SAndroid Build Coastguard Worker    # as well, all test comparisons will survive without knowing about this
158*6236dae4SAndroid Build Coastguard Worker    # little quirk.
159*6236dae4SAndroid Build Coastguard Worker
160*6236dae4SAndroid Build Coastguard Worker    if(($$thing =~ /^HTTP\/(1.1|1.0|2|3) [1-5][^\x0d]*\z/) ||
161*6236dae4SAndroid Build Coastguard Worker       ($$thing =~ /^(GET|POST|PUT|DELETE) \S+ HTTP\/\d+(\.\d+)?/) ||
162*6236dae4SAndroid Build Coastguard Worker       (($$thing =~ /^[a-z0-9_-]+: [^\x0d]*\z/i) &&
163*6236dae4SAndroid Build Coastguard Worker        # skip curl error messages
164*6236dae4SAndroid Build Coastguard Worker        ($$thing !~ /^curl: \(\d+\) /))) {
165*6236dae4SAndroid Build Coastguard Worker        # enforce CRLF newline
166*6236dae4SAndroid Build Coastguard Worker        $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
167*6236dae4SAndroid Build Coastguard Worker        $prevupdate = 1;
168*6236dae4SAndroid Build Coastguard Worker    }
169*6236dae4SAndroid Build Coastguard Worker    else {
170*6236dae4SAndroid Build Coastguard Worker        if(($$thing =~ /^\n\z/) && $prevupdate) {
171*6236dae4SAndroid Build Coastguard Worker            # if there's a blank link after a line we update, we hope it is
172*6236dae4SAndroid Build Coastguard Worker            # the empty line following headers
173*6236dae4SAndroid Build Coastguard Worker            $$thing =~ s/\x0a/\x0d\x0a/;
174*6236dae4SAndroid Build Coastguard Worker        }
175*6236dae4SAndroid Build Coastguard Worker        $prevupdate = 0;
176*6236dae4SAndroid Build Coastguard Worker    }
177*6236dae4SAndroid Build Coastguard Worker}
178*6236dae4SAndroid Build Coastguard Worker
179*6236dae4SAndroid Build Coastguard Worker#######################################################################
180*6236dae4SAndroid Build Coastguard Worker# Run the application under test and return its return code
181*6236dae4SAndroid Build Coastguard Worker#
182*6236dae4SAndroid Build Coastguard Workersub runclient {
183*6236dae4SAndroid Build Coastguard Worker    my ($cmd)=@_;
184*6236dae4SAndroid Build Coastguard Worker    my $ret = system($cmd);
185*6236dae4SAndroid Build Coastguard Worker    print "CMD ($ret): $cmd\n" if($verbose && !$torture);
186*6236dae4SAndroid Build Coastguard Worker    return $ret;
187*6236dae4SAndroid Build Coastguard Worker
188*6236dae4SAndroid Build Coastguard Worker# This is one way to test curl on a remote machine
189*6236dae4SAndroid Build Coastguard Worker#    my $out = system("ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'");
190*6236dae4SAndroid Build Coastguard Worker#    sleep 2;    # time to allow the NFS server to be updated
191*6236dae4SAndroid Build Coastguard Worker#    return $out;
192*6236dae4SAndroid Build Coastguard Worker}
193*6236dae4SAndroid Build Coastguard Worker
194*6236dae4SAndroid Build Coastguard Worker#######################################################################
195*6236dae4SAndroid Build Coastguard Worker# Run the application under test and return its stdout
196*6236dae4SAndroid Build Coastguard Worker#
197*6236dae4SAndroid Build Coastguard Workersub runclientoutput {
198*6236dae4SAndroid Build Coastguard Worker    my ($cmd)=@_;
199*6236dae4SAndroid Build Coastguard Worker    return `$cmd 2>$dev_null`;
200*6236dae4SAndroid Build Coastguard Worker
201*6236dae4SAndroid Build Coastguard Worker# This is one way to test curl on a remote machine
202*6236dae4SAndroid Build Coastguard Worker#    my @out = `ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'`;
203*6236dae4SAndroid Build Coastguard Worker#    sleep 2;    # time to allow the NFS server to be updated
204*6236dae4SAndroid Build Coastguard Worker#    return @out;
205*6236dae4SAndroid Build Coastguard Worker}
206*6236dae4SAndroid Build Coastguard Worker
207*6236dae4SAndroid Build Coastguard Worker
208*6236dae4SAndroid Build Coastguard Worker#######################################################################
209*6236dae4SAndroid Build Coastguard Worker# Quote an argument for passing safely to a Bourne shell
210*6236dae4SAndroid Build Coastguard Worker# This does the same thing as String::ShellQuote but doesn't need a package.
211*6236dae4SAndroid Build Coastguard Worker#
212*6236dae4SAndroid Build Coastguard Workersub shell_quote {
213*6236dae4SAndroid Build Coastguard Worker    my ($s)=@_;
214*6236dae4SAndroid Build Coastguard Worker    if($^O eq 'MSWin32') {
215*6236dae4SAndroid Build Coastguard Worker        $s = '"' . $s . '"';
216*6236dae4SAndroid Build Coastguard Worker    }
217*6236dae4SAndroid Build Coastguard Worker    else {
218*6236dae4SAndroid Build Coastguard Worker        if($s !~ m/^[-+=.,_\/:a-zA-Z0-9]+$/) {
219*6236dae4SAndroid Build Coastguard Worker            # string contains a "dangerous" character--quote it
220*6236dae4SAndroid Build Coastguard Worker            $s =~ s/'/'"'"'/g;
221*6236dae4SAndroid Build Coastguard Worker            $s = "'" . $s . "'";
222*6236dae4SAndroid Build Coastguard Worker        }
223*6236dae4SAndroid Build Coastguard Worker    }
224*6236dae4SAndroid Build Coastguard Worker    return $s;
225*6236dae4SAndroid Build Coastguard Worker}
226*6236dae4SAndroid Build Coastguard Worker
227*6236dae4SAndroid Build Coastguard Workersub get_sha256_base64 {
228*6236dae4SAndroid Build Coastguard Worker    my ($file_path) = @_;
229*6236dae4SAndroid Build Coastguard Worker    return encode_base64(sha256(do { local $/; open my $fh, '<:raw', $file_path or die $!; <$fh> }), "");
230*6236dae4SAndroid Build Coastguard Worker}
231*6236dae4SAndroid Build Coastguard Worker
232*6236dae4SAndroid Build Coastguard Workersub subsha256base64file {
233*6236dae4SAndroid Build Coastguard Worker    my ($thing) = @_;
234*6236dae4SAndroid Build Coastguard Worker
235*6236dae4SAndroid Build Coastguard Worker    # SHA-256 base64
236*6236dae4SAndroid Build Coastguard Worker    while ($$thing =~ s/%sha256b64file\[(.*?)\]sha256b64file%/%%SHA256B64FILE%%/i) {
237*6236dae4SAndroid Build Coastguard Worker        my $file_path = $1;
238*6236dae4SAndroid Build Coastguard Worker        $file_path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
239*6236dae4SAndroid Build Coastguard Worker        my $hash_b64 = get_sha256_base64($file_path);
240*6236dae4SAndroid Build Coastguard Worker        $$thing =~ s/%%SHA256B64FILE%%/$hash_b64/;
241*6236dae4SAndroid Build Coastguard Worker    }
242*6236dae4SAndroid Build Coastguard Worker}
243*6236dae4SAndroid Build Coastguard Worker
244*6236dae4SAndroid Build Coastguard Workersub get_file_content {
245*6236dae4SAndroid Build Coastguard Worker    my ($file_path) = @_;
246*6236dae4SAndroid Build Coastguard Worker    my $content = do { local $/; open my $fh, '<', $file_path or die $!; <$fh> };
247*6236dae4SAndroid Build Coastguard Worker    $content =~ s/(^|-----END .*?-----[\r\n]?)(.*?)(-----BEGIN .*?-----|$)/$1$3/gs;
248*6236dae4SAndroid Build Coastguard Worker    $content =~ s/\r\n/\n/g;
249*6236dae4SAndroid Build Coastguard Worker    chomp($content);
250*6236dae4SAndroid Build Coastguard Worker    return $content;
251*6236dae4SAndroid Build Coastguard Worker}
252*6236dae4SAndroid Build Coastguard Worker
253*6236dae4SAndroid Build Coastguard Workersub substrippemfile {
254*6236dae4SAndroid Build Coastguard Worker    my ($thing) = @_;
255*6236dae4SAndroid Build Coastguard Worker
256*6236dae4SAndroid Build Coastguard Worker    # File content substitution
257*6236dae4SAndroid Build Coastguard Worker    while ($$thing =~ s/%strippemfile\[(.*?)\]strippemfile%/%%FILE%%/i) {
258*6236dae4SAndroid Build Coastguard Worker        my $file_path = $1;
259*6236dae4SAndroid Build Coastguard Worker        $file_path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
260*6236dae4SAndroid Build Coastguard Worker        my $file_content = get_file_content($file_path);
261*6236dae4SAndroid Build Coastguard Worker        $$thing =~ s/%%FILE%%/$file_content/;
262*6236dae4SAndroid Build Coastguard Worker    }
263*6236dae4SAndroid Build Coastguard Worker}
264*6236dae4SAndroid Build Coastguard Worker1;
265