diff stream_upstream_random.t @ 1350:fda743e92b31

Tests: upstream random tests.
author Sergey Kandaurov <pluknet@nginx.com>
date Fri, 15 Jun 2018 13:59:08 +0300
parents
children a37d8526e691
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/stream_upstream_random.t
@@ -0,0 +1,309 @@
+#!/usr/bin/perl
+
+# (C) Sergey Kandaurov
+# (C) Nginx, Inc.
+
+# Tests for upstream random balancer module.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+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_zone stream_upstream_random/)
+	->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+worker_processes 2;
+
+events {
+}
+
+stream {
+    upstream u {
+        zone z 1m;
+        random;
+        server 127.0.0.1:8081;
+        server 127.0.0.1:8082;
+    }
+
+    upstream lc {
+        zone lc 1m;
+        random two;
+        server 127.0.0.1:8081;
+        server 127.0.0.1:8082;
+    }
+
+    upstream w {
+        zone w 1m;
+        random two least_conn;
+        server 127.0.0.1:8081;
+        server 127.0.0.1:8082 weight=2;
+    }
+
+    upstream mc {
+        zone mc 1m;
+        random;
+        server 127.0.0.1:8081 max_conns=2;
+        server 127.0.0.1:8082 max_conns=1;
+    }
+
+    upstream mc2 {
+        zone mc 1m;
+        random two;
+        server 127.0.0.1:8081 max_conns=2;
+        server 127.0.0.1:8082 max_conns=1;
+    }
+
+    upstream one {
+        random;
+        server 127.0.0.1:8081;
+    }
+
+    upstream two {
+        random two;
+        server 127.0.0.1:8081;
+    }
+
+    upstream zone {
+        zone z 1m;
+        random;
+        server 127.0.0.1:8081;
+    }
+
+    upstream ztwo {
+        zone z 1m;
+        random two;
+        server 127.0.0.1:8081;
+    }
+
+    upstream fail {
+        zone fail 1m;
+        random;
+        server 127.0.0.1:8096;
+        server 127.0.0.1:8083 down;
+        server 127.0.0.1:8082;
+    }
+
+    upstream fail2 {
+        zone fail2 1m;
+        random two;
+        server 127.0.0.1:8096;
+        server 127.0.0.1:8083 down;
+        server 127.0.0.1:8082;
+    }
+
+    server {
+        listen      127.0.0.1:8080;
+        proxy_pass  u;
+    }
+
+    server {
+        listen      127.0.0.1:8083;
+        proxy_pass  lc;
+    }
+
+    server {
+        listen      127.0.0.1:8084;
+        proxy_pass  w;
+    }
+
+    server {
+        listen      127.0.0.1:8085;
+        proxy_pass  mc;
+    }
+
+    server {
+        listen      127.0.0.1:8086;
+        proxy_pass  mc2;
+    }
+
+    server {
+        listen      127.0.0.1:8087;
+        proxy_pass  one;
+    }
+
+    server {
+        listen      127.0.0.1:8088;
+        proxy_pass  two;
+    }
+
+    server {
+        listen      127.0.0.1:8089;
+        proxy_pass  zone;
+    }
+
+    server {
+        listen      127.0.0.1:8090;
+        proxy_pass  ztwo;
+    }
+
+    proxy_connect_timeout 1s;
+
+    server {
+        listen      127.0.0.1:8091;
+        proxy_pass  fail;
+    }
+
+    server {
+        listen      127.0.0.1:8092;
+        proxy_pass  fail2;
+    }
+}
+
+EOF
+
+$t->run_daemon(\&http_daemon, port(8081));
+$t->run_daemon(\&http_daemon, port(8082));
+$t->try_run('no upstream random')->plan(12);
+
+$t->waitforsocket('127.0.0.1:' . port(8081));
+$t->waitforsocket('127.0.0.1:' . port(8082));
+
+###############################################################################
+
+my @ports = my ($port1, $port2) = (port(8081), port(8082));
+
+like(get(8080, '/'), qr/X-Port: ($port1|$port2)/, 'random');
+like(get(8083, '/'), qr/X-Port: ($port1|$port2)/, 'random two');
+
+my $s = get(8083, '/w', start => 1, sleep => 0.2);
+my $r = get(8083, '/');
+my ($p) = http_end($s) =~ /X-Port: (\d+)/;
+like($r, qr/X-Port: (?!$p)/, 'random wait');
+
+SKIP: {
+skip 'long test', 3 unless $ENV{TEST_NGINX_UNSAFE};
+
+is(parallel(8084, '/w', 3), "$port1: 1, $port2: 2", 'random weight');
+
+is(parallel(8085, '/w', 4), "$port1: 2, $port2: 1", 'max_conns');
+is(parallel(8086, '/w', 4), "$port1: 2, $port2: 1", 'max_conns two');
+
+}
+
+# single variants
+
+like(get(8087, '/'), qr/X-Port: $port1/, 'single one');
+like(get(8088, '/'), qr/X-Port: $port1/, 'single two');
+like(get(8089, '/'), qr/X-Port: $port1/, 'zone one');
+like(get(8090, '/'), qr/X-Port: $port1/, 'zone two');
+
+like(many(8091, '/', 10), qr/$port2: 10/, 'failures');
+like(many(8092, '/', 10), qr/$port2: 10/, 'failures two');
+
+###############################################################################
+
+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 many {
+	my ($port, $uri, $count, %opts) = @_;
+	my %ports;
+
+	for (1 .. $count) {
+		if (get($port, $uri) =~ /X-Port: (\d+)/) {
+			$ports{$1} = 0 unless defined $ports{$1};
+			$ports{$1}++;
+		}
+
+		select undef, undef, undef, $opts{delay} if $opts{delay};
+	}
+
+	my @keys = map { my $p = $_; grep { $p == $_ } keys %ports } @ports;
+	return join ', ', map { $_ . ": " . $ports{$_} } @keys;
+}
+
+sub parallel {
+	my ($port, $uri, $n) = @_;
+	my %ports;
+
+	my @s = map { get($port, $uri, start => 1, sleep => 0.1) } (1 .. $n);
+
+	for (@s) {
+		if (http_end($_) =~ /X-Port: (\d+)/) {
+			$ports{$1} = 0 unless defined $ports{$1};
+			$ports{$1}++;
+		}
+	}
+
+	my @keys = map { my $p = $_; grep { $p == $_ } keys %ports } @ports;
+	return join ', ', map { $_ . ": " . $ports{$_} } @keys;
+}
+
+###############################################################################
+
+sub http_daemon {
+	my ($port) = @_;
+
+	my $server = IO::Socket::INET->new(
+		Proto => 'tcp',
+		LocalHost => '127.0.0.1',
+		LocalPort => $port,
+		Listen => 5,
+		Reuse => 1
+	)
+		or die "Can't create listening socket: $!\n";
+
+	local $SIG{PIPE} = 'IGNORE';
+
+	while (my $client = $server->accept()) {
+		$client->autoflush(1);
+
+		my $headers = '';
+		my $uri = '';
+
+		while (<$client>) {
+			$headers .= $_;
+			last if (/^\x0d?\x0a?$/);
+		}
+
+		$uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
+
+		if ($uri eq '/w') {
+			Test::Nginx::log_core('||', "$port: sleep(2.5)");
+			select undef, undef, undef, 2.5;
+		}
+
+		if ($uri eq '/close' && $port == port(8081)) {
+			next;
+		}
+
+		Test::Nginx::log_core('||', "$port: response, 200");
+		print $client <<EOF;
+HTTP/1.1 200 OK
+Connection: close
+X-Port: $port
+
+OK
+EOF
+
+		close $client;
+	}
+}
+
+###############################################################################