diff options
Diffstat (limited to 'regress')
-rw-r--r-- | regress/tests/Httpd.pm | 5 | ||||
-rw-r--r-- | regress/tests/LICENSE | 2 | ||||
-rw-r--r-- | regress/tests/Makefile | 34 | ||||
-rw-r--r-- | regress/tests/README | 10 | ||||
-rw-r--r-- | regress/tests/args-get-1048576.pl | 2 | ||||
-rw-r--r-- | regress/tests/args-get-1073741824.pl | 2 | ||||
-rw-r--r-- | regress/tests/args-get-512.pl | 2 | ||||
-rw-r--r-- | regress/tests/args-get-slash.pl | 4 | ||||
-rw-r--r-- | regress/tests/funcs.pl | 182 |
9 files changed, 110 insertions, 133 deletions
diff --git a/regress/tests/Httpd.pm b/regress/tests/Httpd.pm index d5b9df0..485ff68 100644 --- a/regress/tests/Httpd.pm +++ b/regress/tests/Httpd.pm @@ -1,4 +1,4 @@ -# $OpenBSD: Httpd.pm,v 1.1 2015/07/16 16:35:57 reyk Exp $ +# $OpenBSD: Httpd.pm,v 1.2 2017/01/30 21:18:24 reyk Exp $ # Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org> # Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org> @@ -27,6 +27,7 @@ sub new { my $class = shift; my %args = @_; $args{chroot} ||= "."; + $args{docroot} ||= "htdocs"; $args{logfile} ||= $args{chroot}."/httpd.log"; $args{up} ||= $args{dryrun} || "server_launch: "; $args{down} ||= $args{dryrun} ? "httpd.conf:" : "parent terminating"; @@ -54,7 +55,7 @@ sub new { my $listenport = $self->{listenport}; print $fh "prefork 1\n"; # only crashes of first child are observed - print $fh "chroot \"".$args{chroot}."\"\n"; + print $fh "chroot \"".$args{docroot}."\"\n"; print $fh "logdir \"".$args{chroot}."\"\n"; my @http = @{$self->{http}}; diff --git a/regress/tests/LICENSE b/regress/tests/LICENSE index 8f60827..a5303a4 100644 --- a/regress/tests/LICENSE +++ b/regress/tests/LICENSE @@ -1,4 +1,4 @@ -# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org> +# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org> # Copyright (c) 2014,2015 Reyk Floeter <reyk@openbsd.org> # # Permission to use, copy, modify, and distribute this software for any diff --git a/regress/tests/Makefile b/regress/tests/Makefile index 5298c7c..1c5c1ec 100644 --- a/regress/tests/Makefile +++ b/regress/tests/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 2015/07/16 17:00:41 reyk Exp $ +# $OpenBSD: Makefile,v 1.8 2017/07/14 13:31:44 bluhm Exp $ # The following ports must be installed for the regression tests: # p5-IO-Socket-INET6 object interface for AF_INET and AF_INET6 domain sockets @@ -17,18 +17,9 @@ PERL_REQUIRE != perl -Mstrict -Mwarnings -e ' \ regress: @echo "${PERL_REQUIRE}" @echo install these perl packages for additional tests + @echo SKIPPED .endif -# Fill out these variables if you want to test httpd with -# the httpd process running on a remote machine. You have to specify -# a local and remote ip address for the tcp connections. To control -# the remote machine you need a hostname for ssh to log in. All the -# test files must be in the same directory local and remote. - -LOCAL_ADDR ?= -REMOTE_ADDR ?= -REMOTE_SSH ?= - # Automatically generate regress targets from test cases in directory. ARGS != cd ${.CURDIR} && ls args-*.pl @@ -37,10 +28,10 @@ REGRESS_TARGETS = ${TARGETS:S/^/run-regress-/} CLEANFILES += *.log httpd.conf ktrace.out stamp-* CLEANFILES += *.pem *.req *.crt *.key *.srl md5-* -HTDOCS = 512 1048576 1073741824 -HTDOCS_MD5 = ${HTDOCS:S/^/${.OBJDIR}\/md5-/} +HTDOCS_FILES = 512 1048576 1073741824 +HTDOCS_MD5 = ${HTDOCS_FILES:S,^,md5-,} HTDOCS_SPARSE = yes -CLEANFILES += ${HTDOCS} +CLEANFILES += htdocs/* # Set variables so that make runs with and without obj directory. # Only do that if necessary to keep visible output short. @@ -62,19 +53,20 @@ run-regress-$a: $a ${HTDOCS_MD5} time SUDO=${SUDO} KTRACE=${KTRACE} HTTPD=${HTTPD} perl ${PERLINC} ${PERLPATH}httpd.pl ${.OBJDIR} ${PERLPATH}$a .endfor -# htdocs +# populate htdocs -.for d in ${HTDOCS} -${.OBJDIR}/$d: +.for d in ${HTDOCS_FILES} +htdocs/$d: @echo '\n======== file: $d ========' + mkdir -m 0755 -p ${@:H} .if (${HTDOCS_SPARSE} != "yes") - @dd if=/dev/arandom of=$@ count=$$(($d / 512)) bs=512 + dd if=/dev/arandom of=$@ count=$$(($d / 512)) bs=512 .else - @dd of=$@ seek=$$(($d / 512)) bs=512 count=0 status=none + dd of=$@ seek=$$(($d / 512)) bs=512 count=0 status=none .endif -${.OBJDIR}/md5-$d: ${.OBJDIR}/$d - @md5 -q ${.OBJDIR}/$d > $@ +md5-$d: htdocs/$d + md5 -q htdocs/$d >$@ .endfor # create certificates for TLS diff --git a/regress/tests/README b/regress/tests/README index c9c7836..0d2c8c0 100644 --- a/regress/tests/README +++ b/regress/tests/README @@ -1,16 +1,16 @@ -Run httpd regressions tests. The framework runs a client and a httpd. +Run httpd regression tests. The framework runs a client and an httpd. Each test creates a special httpd.conf and starts those two processes. All processes write log files that are checked for certain messages. The test arguments are kept in the args-*.pl files. -SUDO=sudo -As httpd needs root privileges either run the tests as root or set +SUDO=doas +As httpd needs root privileges, either run the tests as root or set this variable and run make as a regular user. Only the code that -requires it, is run as root. +requires it is run as root. KTRACE=ktrace Set this variable if you want a ktrace output from httpd. Note that -ktrace is invoked after sudo as sudo would disable it. +ktrace is invoked after SUDO as SUDO would disable it. HTTPD=/usr/src/usr.sbin/httpd/obj/httpd Start an alternative httpd program that is not in the path. diff --git a/regress/tests/args-get-1048576.pl b/regress/tests/args-get-1048576.pl index 9253aec..fa06bba 100644 --- a/regress/tests/args-get-1048576.pl +++ b/regress/tests/args-get-1048576.pl @@ -6,7 +6,7 @@ our %args = ( client => { path => "$len", len => $len, - http_vers => [ "1.0" ], + http_vers => [ "1.0" ], }, len => 1048576, md5 => path_md5("$len") diff --git a/regress/tests/args-get-1073741824.pl b/regress/tests/args-get-1073741824.pl index 2b4c5f4..c27e00d 100644 --- a/regress/tests/args-get-1073741824.pl +++ b/regress/tests/args-get-1073741824.pl @@ -6,7 +6,7 @@ my @lengths = ($len, $len); our %args = ( client => { path => "$len", - http_vers => [ "1.0" ], + http_vers => [ "1.0" ], lengths => \@lengths, }, md5 => path_md5("$len"), diff --git a/regress/tests/args-get-512.pl b/regress/tests/args-get-512.pl index 20e92c4..6a0b79a 100644 --- a/regress/tests/args-get-512.pl +++ b/regress/tests/args-get-512.pl @@ -6,7 +6,7 @@ my @lengths = ($len, $len, $len); our %args = ( client => { path => "$len", - http_vers => [ "1.0" ], + http_vers => [ "1.0" ], lengths => \@lengths, }, md5 => path_md5("$len"), diff --git a/regress/tests/args-get-slash.pl b/regress/tests/args-get-slash.pl index 9406f4b..e3e7a3b 100644 --- a/regress/tests/args-get-slash.pl +++ b/regress/tests/args-get-slash.pl @@ -7,11 +7,11 @@ our %args = ( my $self = shift; print "GET /\r\n\r\n"; }, - nocheck => 1 + nocheck => 1 }, httpd => { loggrep => { - qr/"GET \/" 500 0/ => 1, + qr/"GET \/" 400 0/ => 1, }, }, ); diff --git a/regress/tests/funcs.pl b/regress/tests/funcs.pl index beda09a..fde3807 100644 --- a/regress/tests/funcs.pl +++ b/regress/tests/funcs.pl @@ -1,6 +1,6 @@ -# $OpenBSD: funcs.pl,v 1.6 2016/05/03 19:13:04 bluhm Exp $ +# $OpenBSD: funcs.pl,v 1.8 2017/07/14 13:31:44 bluhm Exp $ -# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org> +# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org> # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -188,9 +188,12 @@ sub http_request { sub http_response { my ($self, $len) = @_; my $method = $self->{method} || "GET"; + my $code = $self->{code} || "200 OK"; my $vers; my $chunked = 0; + my $multipart = 0; + my $boundary; { local $/ = "\r\n"; local $_ = <STDIN>; @@ -198,8 +201,8 @@ sub http_response { or die ref($self), " missing http $len response"; chomp; print STDERR "<<< $_\n"; - m{^HTTP/(\d\.\d) 200 OK$} - or die ref($self), " http response not ok" + m{^HTTP/(\d\.\d) $code$} + or die ref($self), " http response not $code" unless $self->{httpnok}; $vers = $1; while (<STDIN>) { @@ -207,7 +210,7 @@ sub http_response { print STDERR "<<< $_\n"; last if /^$/; if (/^Content-Length: (.*)/) { - if ($self->{httpnok}) { + if ($self->{httpnok} or $self->{multipart}) { $len = $1; } else { $1 == $len or die ref($self), @@ -217,12 +220,20 @@ sub http_response { if (/^Transfer-Encoding: chunked$/) { $chunked = 1; } + if (/^Content-Type: multipart\/byteranges; boundary=(.*)$/) { + $multipart = 1; + $boundary = $1; + } } } - if ($chunked) { + die ref($self), " no multipart response" + if ($self->{multipart} && $multipart == 0); + + if ($multipart) { + read_multipart($self, $boundary); + } elsif ($chunked) { read_chunked($self); } else { - #$len = $vers eq "1.1" ? $len : undef; read_char($self, $len) if $method eq "GET"; } @@ -265,6 +276,47 @@ sub read_chunked { } } +sub read_multipart { + my $self = shift; + my $boundary = shift; + my $ctx = Digest::MD5->new(); + my $len = 0; + + for (;;) { + my $part = 0; + { + local $/ = "\r\n"; + local $_ = <STDIN>; + local $_ = <STDIN>; + defined or die ref($self), " missing boundary"; + chomp; + print STDERR "<<< $_\n"; + /^--$boundary(--)?$/ + or die ref($self), " boundary not found: $_"; + if (not $1) { + while (<STDIN>) { + chomp; + if (/^Content-Length: (.*)/) { + $part = $1; + } + if (/^Content-Range: bytes (\d+)-(\d+)\/(\d+)$/) { + $part = $2 - $1 + 1; + } + print STDERR "<<< $_\n"; + last if /^$/; + } + } + } + last unless $part > 0; + + $len += read_part($self, $ctx, $part); + } + + print STDERR "LEN: ", $len, "\n"; + print STDERR "MD5: ", $ctx->hexdigest, "\n"; + +} + sub errignore { $SIG{PIPE} = 'IGNORE'; $SIG{__DIE__} = sub { @@ -277,7 +329,7 @@ sub errignore { } ######################################################################## -# Server funcs +# Common funcs ######################################################################## sub read_char { @@ -285,107 +337,39 @@ sub read_char { my $max = shift // $self->{max}; my $ctx = Digest::MD5->new(); - my $len = 0; - if (defined($max) && $max == 0) { - print STDERR "Max\n"; - } else { - while ((my $r = sysread(STDIN, my $buf, POSIX::BUFSIZ))) { - my $pct; - $_ = $buf; - $len += $r; - $ctx->add($_); - $pct = ($len / $max) * 100.0; - printf(STDERR "%.2f%%\n", $pct); - if (defined($max) && $len >= $max) { - print STDERR "\nMax"; - last; - } - } - print STDERR "\n"; - } + my $len = read_part($self, $ctx, $max); print STDERR "LEN: ", $len, "\n"; print STDERR "MD5: ", $ctx->hexdigest, "\n"; } -sub http_server { +sub read_part { my $self = shift; - my %header = %{$self->{header} || { Server => "Perl/".$^V }}; - my $cookie = $self->{cookie} || ""; + my ($ctx, $max) = @_; - my($method, $url, $vers); - do { - my $len; - { - local $/ = "\r\n"; - local $_ = <STDIN>; - return unless defined $_; - chomp; - print STDERR "<<< $_\n"; - ($method, $url, $vers) = m{^(\w+) (.*) HTTP/(1\.[01])$} - or die ref($self), " http request not ok"; - $method =~ /^(GET|PUT)$/ - or die ref($self), " unknown method: $method"; - ($len, my @chunks) = $url =~ /(\d+)/g; - $len = [ $len, @chunks ] if @chunks; - while (<STDIN>) { - chomp; - print STDERR "<<< $_\n"; - last if /^$/; - if ($method eq "PUT" && - /^Content-Length: (.*)/) { - $1 == $len or die ref($self), - " bad content length $1"; - } - $cookie ||= $1 if /^Cookie: (.*)/; - } - } - if ($method eq "PUT" ) { - if (ref($len) eq 'ARRAY') { - read_chunked($self); - } else { - read_char($self, $len); - } - } - - my @response = ("HTTP/$vers 200 OK"); - $len = defined($len) ? $len : scalar(split /|/,$url); - if ($vers eq "1.1" && $method eq "GET") { - if (ref($len) eq 'ARRAY') { - push @response, "Transfer-Encoding: chunked"; - } else { - push @response, "Content-Length: $len"; - } + my $opct = 0; + my $len = 0; + for (;;) { + if (defined($max) && $len >= $max) { + print STDERR "Max\n"; + last; } - foreach my $key (sort keys %header) { - my $val = $header{$key}; - if (ref($val) eq 'ARRAY') { - push @response, "$key: $_" - foreach @{$val}; - } else { - push @response, "$key: $val"; - } + my $rlen = POSIX::BUFSIZ; + if (defined($max) && $rlen > $max - $len) { + $rlen = $max - $len; } - push @response, "Set-Cookie: $cookie" if $cookie; - push @response, ""; - - print STDERR map { ">>> $_\n" } @response; - print map { "$_\r\n" } @response; - - if ($method eq "GET") { - if (ref($len) eq 'ARRAY') { - if ($vers eq "1.1") { - write_chunked($self, @$len); - } else { - write_char($self, $_) foreach (@$len); - } - } else { - write_char($self, $len); - } + defined(my $n = read(STDIN, my $buf, $rlen)) + or die ref($self), " read failed: $!"; + $n or last; + $len += $n; + $ctx->add($buf); + my $pct = ($len / $max) * 100.0; + if ($pct >= $opct + 1) { + printf(STDERR "%.2f%% $len/$max\n", $pct); + $opct = $pct; } - IO::Handle::flush(\*STDOUT); - } while ($vers eq "1.1"); - $self->{redo}-- if $self->{redo}; + } + return $len; } sub write_chunked { |