Mercurial > hg > nginx-tests
changeset 1391:62f06d8dfc63
Tests: ported upstream max_conns tests to stream, reduced diffs.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Wed, 07 Nov 2018 14:49:34 +0300 |
parents | 2c0955286894 |
children | dab8b5252216 |
files | stream_upstream_max_conns.t upstream_max_conns.t |
diffstat | 2 files changed, 388 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stream_upstream_max_conns.t Wed Nov 07 14:49:34 2018 +0300 @@ -0,0 +1,379 @@ +#!/usr/bin/perl + +# (C) Nginx, Inc. +# (C) Sergey Kandaurov + +# Tests for stream upstream module with max_conns feature. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +use IO::Select; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx qw/ :DEFAULT http_end /; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/stream stream_upstream_least_conn/) + ->plan(12); + +$t->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +stream { + upstream u_unlim { + server 127.0.0.1:8081 max_conns=0; + server 127.0.0.1:8082; + } + upstream u_lim { + server 127.0.0.1:8081 max_conns=3; + } + + upstream u_backup { + server 127.0.0.1:8081 max_conns=2; + server 127.0.0.1:8082 backup; + } + upstream u_backup_lim { + server 127.0.0.1:8081 max_conns=2; + server 127.0.0.1:8082 backup max_conns=3; + } + + upstream u_two { + server 127.0.0.1:8081 max_conns=1; + server 127.0.0.1:8082 max_conns=1; + } + upstream u_some { + server 127.0.0.1:8081 max_conns=1; + server 127.0.0.1:8082; + } + upstream u_many { + server 127.0.0.1:8081 max_conns=1; + server 127.0.0.1:8081 max_conns=1; + server 127.0.0.1:8082; + } + + upstream u_weight { + server 127.0.0.1:8081 weight=2 max_conns=1; + server 127.0.0.1:8082; + } + + upstream u_lc { + least_conn; + server 127.0.0.1:8081 max_conns=1; + server 127.0.0.1:8082; + } + upstream u_lc_backup { + least_conn; + server 127.0.0.1:8081 max_conns=2; + server 127.0.0.1:8082 backup; + } + upstream u_lc_backup_lim { + least_conn; + server 127.0.0.1:8081 max_conns=2; + server 127.0.0.1:8082 backup max_conns=3; + } + + server { + listen 127.0.0.1:8086; + proxy_pass u_unlim; + } + + server { + listen 127.0.0.1:8087; + proxy_pass u_lim; + } + + server { + listen 127.0.0.1:8088; + proxy_pass u_backup; + } + + server { + listen 127.0.0.1:8089; + proxy_pass u_backup_lim; + } + + server { + listen 127.0.0.1:8090; + proxy_pass u_two; + } + + server { + listen 127.0.0.1:8091; + proxy_pass u_some; + } + + server { + listen 127.0.0.1:8092; + proxy_pass u_many; + } + + server { + listen 127.0.0.1:8093; + proxy_pass u_weight; + } + + server { + listen 127.0.0.1:8094; + proxy_pass u_lc; + } + + server { + listen 127.0.0.1:8095; + proxy_pass u_lc_backup; + } + + server { + listen 127.0.0.1:8096; + proxy_pass u_lc_backup_lim; + } +} + +EOF + +$t->run_daemon(\&http_daemon, port(8081), port(8082), port(8085)); +$t->run(); + +$t->waitforsocket('127.0.0.1:' . port(8081)); +$t->waitforsocket('127.0.0.1:' . port(8082)); +$t->waitforsocket('127.0.0.1:' . port(8085)); + +############################################################################### + +my @ports = my ($p1, $p2) = (port(8081), port(8082)); + +# two peers without max_conns + +is(parallel(8086, '/u_unlim?delay=0', 4), "$p1: 2, $p2: 2", 'unlimited'); + +# reopen connection to test connection subtraction + +my @s = http_get_multi(8087, '/u_lim', 2, 1.1); +get(8087, '/close'); +push @s, http_get_multi(8087, '/u_lim', 1, 1.1); +get(8085, '/closeall'); + +is(http_end_multi(\@s), "$p1: 3", 'conn subtraction'); + +# simple test with limited peer + +is(parallel(8087, '/u_lim', 4), "$p1: 3", 'single'); + +# limited peer with backup peer + +is(peers(8088, '/u_backup', 6), "$p1 $p1 $p2 $p2 $p2 $p2", 'backup'); + +# peer and backup peer, both limited + +is(peers(8089, '/u_backup_lim', 6), "$p1 $p1 $p2 $p2 $p2 ", 'backup limited'); + +# all peers limited + +is(parallel(8090, '/u_two', 4), "$p1: 1, $p2: 1", 'all peers'); + +# subset of peers limited + +is(parallel(8091, '/u_some', 4), "$p1: 1, $p2: 3", 'some peers'); + +# ensure that peer "weight" does not affect its max_conns limit + +is(parallel(8093, '/u_weight', 4), "$p1: 1, $p2: 3", 'weight'); + +# peers with equal server value aggregate max_conns limit + +is(parallel(8092, '/u_many', 6), "$p1: 2, $p2: 4", 'equal peer'); + +# least_conn balancer tests + +is(parallel(8094, '/u_lc', 4), "$p1: 1, $p2: 3", 'least_conn'); +is(peers(8095, '/u_lc_backup', 6), "$p1 $p1 $p2 $p2 $p2 $p2", + 'least_conn backup'); +is(peers(8096, '/u_lc_backup_lim', 6), "$p1 $p1 $p2 $p2 $p2 ", + 'least_conn backup limited'); + +############################################################################### + +sub peers { + my ($port, $uri, $count) = @_; + + my @sockets = http_get_multi($port, $uri, $count, 1.1); + get(8085, '/closeall'); + + join ' ', map { defined $_ && /X-Port: (\d+)/ && $1 } + map { http_end $_ } (@sockets); +} + +sub parallel { + my ($port, $uri, $count) = @_; + + my @sockets = http_get_multi($port, $uri, $count); + for (1 .. 20) { + last if IO::Select->new(@sockets)->can_read(3) == $count; + select undef, undef, undef, 0.01; + } + get(8085, '/closeall'); + return http_end_multi(\@sockets); +} + +sub get { + my ($port, $uri, %opts) = @_; + my $s = IO::Socket::INET->new( + Proto => 'tcp', + PeerAddr => '127.0.0.1', + PeerPort => port($port), + ) + or die "Can't connect to nginx: $!\n"; + + http_get($uri, socket => $s, %opts); +} + +sub http_get_multi { + my ($port, $uri, $count, $wait) = @_; + my @sockets; + + for (0 .. $count - 1) { + $sockets[$_] = get($port, $uri, start => 1); + IO::Select->new($sockets[$_])->can_read($wait) if $wait; + } + + return @sockets; +} + +sub http_end_multi { + my ($sockets) = @_; + my %ports; + + for my $sock (@$sockets) { + my $r = http_end($sock); + if ($r && $r =~ /X-Port: (\d+)/) { + $ports{$1} = 0 unless defined $ports{$1}; + $ports{$1}++; + } + close $sock; + } + + my @keys = map { my $p = $_; grep { $p == $_ } keys %ports } @ports; + return join ', ', map { $_ . ": " . $ports{$_} } @keys; +} + +############################################################################### + +sub http_daemon { + my (@ports) = @_; + my (@socks, @clients); + + for my $port (@ports) { + my $server = IO::Socket::INET->new( + Proto => 'tcp', + LocalHost => "127.0.0.1:$port", + Listen => 42, + Reuse => 1 + ) + or die "Can't create listening socket: $!\n"; + push @socks, $server; + } + + my $sel = IO::Select->new(@socks); + my $skip = 4; + my $count = 0; + + local $SIG{PIPE} = 'IGNORE'; + +OUTER: + while (my @ready = $sel->can_read) { + foreach my $fh (@ready) { + if (grep $_ == $fh, @socks) { + my $new = $fh->accept; + $new->autoflush(1); + $sel->add($new); + $count++; + + } else { + my @busy = grep { $_->sockport() } @ready; + + # finish other handles + if ($fh->sockport() == port(8085) && @busy > 1 + && grep $_->sockport() != port(8085), + @busy) + { + next; + } + + # late events in other handles + if ($fh->sockport() == port(8085) && @busy == 1 + && $count > 1 && $skip-- > 0) + { + select undef, undef, undef, 0.1; + next OUTER; + } + + my $rv = process_socket($fh, \@clients); + if ($rv == 1) { + $sel->remove($fh); + $fh->close; + } + if ($rv == 2) { + for (@clients) { + $sel->remove($_); + $_->close; + } + $sel->remove($fh); + $fh->close; + $skip = 4; + } + $count--; + } + } + } +} + +# Returns true to close connection + +sub process_socket { + my ($client, $saved) = @_; + my $port = $client->sockport(); + + my $headers = ''; + my $uri = ''; + + while (<$client>) { + $headers .= $_; + last if (/^\x0d?\x0a?$/); + } + return 1 if $headers eq ''; + + $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; + return 1 if $uri eq ''; + + Test::Nginx::log_core('||', "$port: response, 200"); + print $client <<EOF; +HTTP/1.1 200 OK +X-Port: $port + +OK +EOF + + return 2 if $uri =~ /closeall/; + return 1 if $uri =~ /close/; + + push @$saved, $client; + return 0; +} + +###############################################################################
--- a/upstream_max_conns.t Tue Nov 06 20:33:13 2018 +0300 +++ b/upstream_max_conns.t Wed Nov 07 14:49:34 2018 +0300 @@ -23,8 +23,8 @@ select STDERR; $| = 1; select STDOUT; $| = 1; -my $t = Test::Nginx->new() - ->has(qw/http proxy rewrite upstream_least_conn upstream_ip_hash/); +my $t = Test::Nginx->new()->has(qw/http proxy rewrite upstream_least_conn/) + ->has(qw/upstream_ip_hash/)->plan(14); $t->write_file_expand('nginx.conf', <<'EOF'); @@ -132,9 +132,8 @@ EOF - $t->run_daemon(\&http_daemon, port(8081), port(8082), port(8085)); -$t->run()->plan(14); +$t->run(); $t->waitforsocket('127.0.0.1:' . port(8081)); $t->waitforsocket('127.0.0.1:' . port(8082)); @@ -148,18 +147,18 @@ is(parallel('/u_unlim?delay=0', 4), "$p1: 2, $p2: 2", 'unlimited'); -# simple test with limited peer - -is(parallel('/u_lim', 4), "$p1: 3", 'single'); - # reopen connection to test connection subtraction -my @s = http_get_multi('/u_lim', 1, 1.1); +my @s = http_get_multi('/u_lim', 2, 1.1); http_get('/u_lim/close'); push @s, http_get_multi('/u_lim', 1, 1.1); http_get('/closeall'); -is(http_end_multi(\@s), "$p1: 2", 'conn subtraction'); +is(http_end_multi(\@s), "$p1: 3", 'conn subtraction'); + +# simple test with limited peer + +is(parallel('/u_lim', 4), "$p1: 3", 'single'); # limited peer with backup peer