[PATCH 3 of 3] Tests: Update and add tests for Age header

Hiroaki Nakamura hnakamur at gmail.com
Fri Jun 14 07:29:24 UTC 2024


# HG changeset patch
# User Hiroaki Nakamura <hnakamur at 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');


More information about the nginx-devel mailing list