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