# HG changeset patch # User Hiroaki Nakamura <hnaka...@gmail.com> # Date 1718345855 -32400 # Fri Jun 14 15:17:35 2024 +0900 # Branch correct_age # Node ID 8473b99b2c169b50bc71c9c07a1f10750b0cfc73 # Parent 51355c41fc134954e58b1534d232291d70252be7 Tests: Update and add tests for Age header.
diff -r 51355c41fc13 -r 8473b99b2c16 h2_proxy_cache_age.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/h2_proxy_cache_age.t Fri Jun 14 15:17:35 2024 +0900 @@ -0,0 +1,198 @@ +#!/usr/bin/perl + +# (C) Sergey Kandaurov +# (C) Nginx, Inc. +# (C) Hiroaki Nakamura + +# Tests for age in HTTP/2 proxy cache. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; +use Test::Nginx::HTTP2; + +use POSIX qw/ ceil /; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/http http_v2 proxy cache/)->plan(8) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { + %%TEST_GLOBALS_HTTP%% + + proxy_cache_path %%TESTDIR%%/cache keys_zone=NAME:1m; + proxy_cache_path %%TESTDIR%%/cache2 keys_zone=NAME2:1m; + + map $arg_slow $rate { + default 8k; + 1 90; + } + + server { + listen 127.0.0.1:8080 http2; + server_name localhost; + + location / { + proxy_pass http://127.0.0.1:8081; + proxy_cache NAME; + proxy_http_version 1.1; + proxy_cache_revalidate on; + } + } + + server { + listen 127.0.0.1:8081; + server_name localhost; + + location / { + proxy_pass http://127.0.0.1:8082; + proxy_cache NAME2; + proxy_http_version 1.1; + proxy_cache_revalidate on; + } + } + + server { + listen 127.0.0.1:8082; + server_name localhost; + + location / { + add_header Cache-Control s-maxage=$arg_ttl; + limit_rate $rate; + } + } +} + +EOF + +$t->write_file('t.html', 'SEE-THIS'); + +# suppress deprecation warning + +open OLDERR, ">&", *STDERR; close STDERR; +$t->run(); +open STDERR, ">&", *OLDERR; + +############################################################################### + +my $s = Test::Nginx::HTTP2->new(); + +my ($path, $sid, $frames, $frame, $t1, $resident_time); + +# normal origin + +wait_until_next_second(); + +$path = '/t.html?ttl=2'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age first'); + +select undef, undef, undef, 2.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 2, 'age hit'); + +select undef, undef, undef, 1.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age updated'); + +SKIP: { +skip 'no exec on win32', 3 if $^O eq 'MSWin32'; + +# slow origin + +wait_until_next_second(); + +$path = '/t.html?ttl=6&slow=1'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 4, 'slow origin first'); + +select undef, undef, undef, 2.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 6, 'slow origin hit'); + +select undef, undef, undef, 1.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 5, 'slow origin updated'); + +} + +# update age after restart + +wait_until_next_second(); + +$path = '/t.html?ttl=20'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age before restart'); +$t1 = time(); + +$t->stop(); + +open OLDERR, ">&", *STDERR; close STDERR; +$t->run(); +open STDERR, ">&", *OLDERR; + +$resident_time = time() - $t1; + +$s = Test::Nginx::HTTP2->new(); + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, $resident_time, 'age after restart'); + +$t->stop(); + +############################################################################### + +# Wait until the next second boundary. +# Calling this before sending a request increases the likelihood that the +# timestamp value does not cross into the next second while sending a request +# and receiving a response. +sub wait_until_next_second { + my $now = time(); + my $next_second = ceil($now); + my $sleep = $next_second - $now; + select undef, undef, undef, $sleep; +} + +############################################################################### diff -r 51355c41fc13 -r 8473b99b2c16 h2_ssl_proxy_cache_age.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/h2_ssl_proxy_cache_age.t Fri Jun 14 15:17:35 2024 +0900 @@ -0,0 +1,243 @@ +#!/usr/bin/perl + +# (C) Sergey Kandaurov +# (C) Nginx, Inc. +# (C) Hiroaki Nakamura + +# Tests for age in HTTP/2 ssl proxy cache. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; +use Test::Nginx::HTTP2; + +use POSIX qw/ ceil /; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new() + ->has(qw/http http_ssl http_v2 proxy cache socket_ssl/)->plan(10) + ->has_daemon('openssl'); + +$t->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { + %%TEST_GLOBALS_HTTP%% + + proxy_cache_path %%TESTDIR%%/cache keys_zone=NAME:1m; + proxy_cache_path %%TESTDIR%%/cache2 keys_zone=NAME2:1m; + + map $arg_slow $rate { + default 8k; + 1 90; + } + + server { + listen 127.0.0.1:8080 http2 ssl; + server_name localhost; + + ssl_certificate_key localhost.key; + ssl_certificate localhost.crt; + + location / { + proxy_pass http://127.0.0.1:8081; + proxy_cache NAME; + proxy_http_version 1.1; + proxy_cache_revalidate on; + } + } + + server { + listen 127.0.0.1:8081; + server_name localhost; + + location / { + proxy_pass http://127.0.0.1:8082; + proxy_cache NAME2; + proxy_http_version 1.1; + proxy_cache_revalidate on; + } + } + + server { + listen 127.0.0.1:8082; + server_name localhost; + + location / { + add_header Cache-Control s-maxage=$arg_ttl; + limit_rate $rate; + } + } +} + +EOF + +$t->write_file('openssl.conf', <<EOF); +[ req ] +default_bits = 2048 +encrypt_key = no +distinguished_name = req_distinguished_name +[ req_distinguished_name ] +EOF + +my $d = $t->testdir(); + +foreach my $name ('localhost') { + system('openssl req -x509 -new ' + . "-config $d/openssl.conf -subj /CN=$name/ " + . "-out $d/$name.crt -keyout $d/$name.key " + . ">>$d/openssl.out 2>&1") == 0 + or die "Can't create certificate for $name: $! "; +} + +$t->write_file('t.html', 'SEE-THIS'); + +open OLDERR, ">&", *STDERR; close STDERR; +$t->run(); +open STDERR, ">&", *OLDERR; + +############################################################################### + +my $s = getconn(port(8080)); +ok($s, 'ssl connection'); + +my ($path, $sid, $frames, $frame, $t1, $resident_time); + +# normal origin + +wait_until_next_second(); + +$path = '/t.html?ttl=2'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age first'); + +select undef, undef, undef, 2.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 2, 'age hit'); + +select undef, undef, undef, 1.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age updated'); + +# slow origin + +SKIP: { +skip 'no exec on win32', 3 if $^O eq 'MSWin32'; + +wait_until_next_second(); + +$path = '/t.html?ttl=6&slow=1'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 4, 'slow origin first'); + +select undef, undef, undef, 2.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 6, 'slow origin hit'); + +select undef, undef, undef, 1.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 5, 'slow origin updated'); + +} + +# update age after restart + +$path = '/t.html?ttl=20'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age before restart'); +$t1 = time(); + +$t->stop(); + +open OLDERR, ">&", *STDERR; close STDERR; +$t->run(); +open STDERR, ">&", *OLDERR; + +$resident_time = time() - $t1; + +$s = getconn(port(8080)); +ok($s, 'ssl connection'); + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, $resident_time, 'age after restart'); + +$t->stop(); + +############################################################################### + +sub getconn { + my ($port) = @_; + my $s; + + eval { + my $sock = Test::Nginx::HTTP2::new_socket($port, SSL => 1, + alpn => 'h2'); + $s = Test::Nginx::HTTP2->new($port, socket => $sock) + if $sock->alpn_selected(); + }; + + return $s if defined $s; + + eval { + my $sock = Test::Nginx::HTTP2::new_socket($port, SSL => 1, + npn => 'h2'); + $s = Test::Nginx::HTTP2->new($port, socket => $sock) + if $sock->next_proto_negotiated(); + }; + + return $s; +} + +# Wait until the next second boundary. +# Calling this before sending a request increases the likelihood that the +# timestamp value does not cross into the next second while sending a request +# and receiving a response. +sub wait_until_next_second { + my $now = time(); + my $next_second = ceil($now); + my $sleep = $next_second - $now; + select undef, undef, undef, $sleep; +} + +############################################################################### diff -r 51355c41fc13 -r 8473b99b2c16 h3_proxy_cache_age.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/h3_proxy_cache_age.t Fri Jun 14 15:17:35 2024 +0900 @@ -0,0 +1,210 @@ +#!/usr/bin/perl + +# (C) Sergey Kandaurov +# (C) Nginx, Inc. +# (C) Hiroaki Nakamura + +# Tests for age in HTTP/3 proxy cache. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; +use Test::Nginx::HTTP3; + +use POSIX qw/ ceil /; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/http http_v3 proxy cryptx/) + ->has_daemon('openssl')->plan(8) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { + %%TEST_GLOBALS_HTTP%% + + ssl_certificate_key localhost.key; + ssl_certificate localhost.crt; + + log_format test $uri:$status:$request_completion; + + proxy_cache_path %%TESTDIR%%/cache keys_zone=NAME:1m; + + map $arg_slow $rate { + default 8k; + 1 90; + } + + server { + listen 127.0.0.1:%%PORT_8980_UDP%% quic; + server_name localhost; + + location / { + proxy_pass http://127.0.0.1:8081/; + proxy_cache NAME; + proxy_http_version 1.1; + proxy_cache_revalidate on; + } + } + + server { + listen 127.0.0.1:8081; + server_name localhost; + + location / { + proxy_pass http://127.0.0.1:8082; + proxy_cache NAME; + proxy_http_version 1.1; + proxy_cache_revalidate on; + } + } + + server { + listen 127.0.0.1:8082; + server_name localhost; + + location / { + add_header Cache-Control s-maxage=$arg_ttl; + limit_rate $rate; + } + } +} + +EOF + +$t->write_file('openssl.conf', <<EOF); +[ req ] +default_bits = 2048 +encrypt_key = no +distinguished_name = req_distinguished_name +[ req_distinguished_name ] +EOF + +my $d = $t->testdir(); + +foreach my $name ('localhost') { + system('openssl req -x509 -new ' + . "-config $d/openssl.conf -subj /CN=$name/ " + . "-out $d/$name.crt -keyout $d/$name.key " + . ">>$d/openssl.out 2>&1") == 0 + or die "Can't create certificate for $name: $! "; +} + +my $content = 'SEE-THIS'; +$t->write_file('t.html', $content); +$t->run(); + +############################################################################### + +my $s = Test::Nginx::HTTP3->new(); + +my ($path, $sid, $frames, $frame, $t1, $resident_time); + +# normal origin + +wait_until_next_second(); + +$path = '/t.html?ttl=2'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age first'); + +select undef, undef, undef, 2.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 2, 'age hit'); + +select undef, undef, undef, 1.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age updated'); + +# slow origin + +wait_until_next_second(); + +$path = '/t.html?ttl=6&slow=1'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 4, 'slow origin first'); + +select undef, undef, undef, 2.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 6, 'slow origin hit'); + +select undef, undef, undef, 1.0; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 5, 'slow origin updated'); + +# update age after restart + +$path = '/t.html?ttl=20'; + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, 0, 'age before restart'); +$t1 = time(); + +$t->stop(); + +open OLDERR, ">&", *STDERR; close STDERR; +$t->run(); +open STDERR, ">&", *OLDERR; + +$resident_time = time() - $t1; + +$s = Test::Nginx::HTTP3->new(); + +$sid = $s->new_stream({ path => $path }); +$frames = $s->read(all => [{ sid => $sid, fin => 1 }]); +($frame) = grep { $_->{type} eq "HEADERS" } @$frames; +is($frame->{headers}->{'age'}, $resident_time, 'age after restart'); + +$t->stop(); + +############################################################################### + +# Wait until the next second boundary. +# Calling this before sending a request increases the likelihood that the +# timestamp value does not cross into the next second while sending a request +# and receiving a response. +sub wait_until_next_second { + my $now = time(); + my $next_second = ceil($now); + my $sleep = $next_second - $now; + select undef, undef, undef, $sleep; +} + +############################################################################### diff -r 51355c41fc13 -r 8473b99b2c16 proxy_cache_age.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proxy_cache_age.t Fri Jun 14 15:17:35 2024 +0900 @@ -0,0 +1,176 @@ +#!/usr/bin/perl + +# (C) Maxim Dounin +# (C) Hiroaki Nakamura + +# Tests for age in http proxy cache. + +############################################################################### + +use warnings; +use strict; + +use Test::More; +use Socket qw/ CRLF /; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; + +use POSIX qw/ ceil /; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(8) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { + %%TEST_GLOBALS_HTTP%% + + proxy_cache_path %%TESTDIR%%/cache levels=1:2 + keys_zone=NAME:1m; + proxy_cache_path %%TESTDIR%%/cache2 levels=1:2 + keys_zone=NAME2:1m; + + map $arg_slow $rate { + default 8k; + 1 100; + } + + server { + listen 127.0.0.1:8080; + server_name localhost; + + location / { + proxy_pass http://127.0.0.1:8081; + proxy_cache NAME; + proxy_http_version 1.1; + proxy_cache_revalidate on; + add_header parent_date $upstream_http_date; + add_header child_msec $msec; + } + } + + server { + listen 127.0.0.1:8081; + server_name localhost; + + location / { + proxy_pass http://127.0.0.1:8082; + proxy_cache NAME2; + proxy_http_version 1.1; + proxy_cache_revalidate on; + add_header origin_date $upstream_http_date; + add_header parent_msec $msec; + } + } + + server { + listen 127.0.0.1:8082; + server_name localhost; + + location / { + add_header Cache-Control $http_x_cache_control; + limit_rate $rate; + add_header origin_msec $msec; + } + } +} + +EOF + +$t->write_file('t.html', 'SEE-THIS'); +$t->write_file('t2.html', 'SEE-THIS'); +$t->write_file('t3.html', 'SEE-THIS'); + +$t->run(); + +############################################################################### + +# normal origin + +wait_until_next_second(); + +like(get('/t.html', 's-maxage=2'), qr/ Age: 0 /, 'age first'); + +sleep 2; + +like(get('/t.html', 's-maxage=2'), qr/ Age: 2 /, 'age hit'); + +sleep 1; + +like(http_get('/t.html'), qr/ Age: 0 /, 'age updated'); + +# slow origin + +SKIP: { +skip 'no exec on win32', 3 if $^O eq 'MSWin32'; + +wait_until_next_second(); + +like(get('/t2.html?slow=1', 's-maxage=6'), qr/ Age: 4 /, + 'slow origin first'); + +sleep 2; + +like(http_get('/t2.html?slow=1'), qr/ Age: 6 /, 'slow origin hit'); + +sleep 1; + +like(http_get('/t2.html?slow=1'), qr/ Age: 5 /, 'slow origin updated'); + +} + +# update age after restart + +wait_until_next_second(); + +like(get('/t3.html', 's-maxage=20'), qr/ Age: 0 /, 'age before restart'); +my $t1 = time(); + +$t->stop(); + +$t->run(); + +my $resident_time = time() - $t1; +like(http_get('/t3.html'), qr/ Age: $resident_time /, + 'age after restart'); + +$t->stop(); + +############################################################################### + +sub get { + my ($url, $extra, %extra) = @_; + return http(<<EOF, %extra); +GET $url HTTP/1.1 +Host: localhost +Connection: close +X-Cache-Control: $extra + +EOF +} + +# Wait until the next second boundary. +# Calling this before sending a request increases the likelihood that the +# timestamp value does not cross into the next second while sending a request +# and receiving a response. +sub wait_until_next_second { + my $now = time(); + my $next_second = ceil($now); + my $sleep = $next_second - $now; + select undef, undef, undef, $sleep; +} + +############################################################################### diff -r 51355c41fc13 -r 8473b99b2c16 proxy_cache_use_stale.t --- a/proxy_cache_use_stale.t Fri Jun 14 15:17:30 2024 +0900 +++ b/proxy_cache_use_stale.t Fri Jun 14 15:17:35 2024 +0900 @@ -206,7 +206,8 @@ $t->write_file('t6.html', 'SEE-THAT'); -my $s = get('/t6.html', 'max-age=1, stale-while-revalidate=2', start => 1); +# max-age must be 5 here since response delay is 4 seconds. +my $s = get('/t6.html', 'max-age=5, stale-while-revalidate=2', start => 1); select undef, undef, undef, 0.2; like(http_get('/t6.html'), qr/UPDATING.*SEE-THIS/s, 's-w-r - updating'); like(http_end($s), qr/STALE.*SEE-THIS/s, 's-w-r - updating stale'); _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel