Skip to content

Commit

Permalink
[ResourceTiming] Refactor connection-reuse tests
Browse files Browse the repository at this point in the history
This CL migrates the connection reuse WPTs to the new style. See
wpt/resource-timing/CodingConventions.md for details.

These tests exist to verify that the Resource Timing API yields correct
PerformanceResourceTiming values when the underlying TCP connection is
reused across multiple subresources.

Bug: 1171767
Change-Id: I5acdb6bf8a5e71bb34c7d2236cdb9d0209d3d04d
GithubIssue: w3c/resource-timing#254
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2950880
Commit-Queue: Tom McKee <[email protected]>
Reviewed-by: Yoav Weiss <[email protected]>
Cr-Commit-Position: refs/heads/master@{#891368}
NOKEYCHECK=True
GitOrigin-RevId: 235b49717de3423fa6d9831a8165dc2b473902f0
  • Loading branch information
tommckee1 authored and copybara-github committed Jun 10, 2021
1 parent b4c1e31 commit 2ea4ed2
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 61 deletions.
38 changes: 38 additions & 0 deletions blink/web_tests/external/wpt/resource-timing/connection-reuse.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,46 @@
<link rel="help" href="https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/entry-invariants.js"></script>
<script src="resources/connection-reuse-test.js"></script>
<script>
const {HTTPS_ORIGIN} = get_host_info();

// Fetches the given subresource a couple times with the same connection.
const http_path = "resources/fake_responses.py";
connection_reuse_test(http_path,
{
'on_200': invariants.assert_tao_pass_no_redirect_http,
'on_304': invariants.assert_tao_pass_304_not_modified_http,
}, "Reuse HTTP connection");

// Like above, but the subresource is fetched over HTTPS while this page is
// fetched over HTTP.
const https_url = `${HTTPS_ORIGIN}/resource-timing/${http_path}`;
connection_reuse_test(https_url,
{
'on_200': invariants.assert_tao_pass_no_redirect_https,
'on_304': invariants.assert_tao_pass_304_not_modified_https,
}, "Reuse HTTPS connection from HTTP page");

// Like the above mixed-content test but the final resource is behind an HTTP
// redirect response.
const redirect_path = (() => {
// The resource behind the redirect is the same fake_responses.py handler
// on the HTTPS origin. Pass it through encodeURIComponent so that it can
// be passed through a query-parameter.
const redirect_url = encodeURIComponent(https_url)
// The request is made to the HTTPS origin with a query parameter that will
// cause a 302 response.
return `${https_url}?redirect=${redirect_url}`;
})();
connection_reuse_test(redirect_path,
{
'on_200': invariants.assert_tao_enabled_cross_origin_redirected_resource,
'on_304': invariants.assert_tao_enabled_cross_origin_redirected_resource,
}, "Reuse HTTPS connection with redirects from an HTTP page");
</script>
</head>
<body>
<h1>Description</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
<script src="/resources/testharnessreport.js"></script>
<script src="resources/entry-invariants.js"></script>
<script src="resources/connection-reuse-test.js"></script>
<script>
connection_reuse_test("resources/fake_responses.py",
{
'on_200': invariants.assert_tao_pass_no_redirect_https,
'on_304': invariants.assert_tao_pass_304_not_modified_https,
}, "Reuse an HTTPS connection");
</script>
</head>
<body>
<h1>Description</h1>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,70 +1,63 @@
// This script is loaded in HTTP and HTTPS contexts to validate
// PerformanceResourceTiming entries' attributes when reusing connections.

// Make the first request before calling 'attribute_test' so that only the
// second request's PerformanceResourceTiming entry will be interrogated.
// We don't check the first request's PerformanceResourceTiming entry because
// that's not what this test is trying to validate.
//
// Note: to ensure that we reuse the connection to fetch multiple resources,
// we use the same XMLHttpRequest object for each request. Although it doesn't
// seem to be specified, each browser tested by WPT will reuse the underlying
// TCP connection with this approach. Pre-establishing the XHR's connection
// helps us to test connection reuse also in browsers that may key their
// connections on the related request's credentials mode.
const client = new XMLHttpRequest();
const identifier = Math.random();
const path = `resources/fake_responses.py?tag=${identifier}`;
client.open("GET", path, false);
client.send();
// Note: to ensure that we reuse the connection to fetch multiple resources, we
// use the same XMLHttpRequest object throughout an individual test. Although
// it doesn't seem to be specified, each browser tested by WPT will reuse the
// underlying TCP connection with this approach. Pre-establishing the XHR's
// connection helps us to test connection reuse also in browsers that may key
// their connections on the related request's credentials mode.

attribute_test(
async () => {
client.open("GET", path + "&same_resource=false", false);
client.send();
const connection_reuse_test = (path, follow_on_assertions, test_label) => {
const {on_200, on_304} = follow_on_assertions;

// We expect to get a 200 Ok response because we've requested a different
// resource than previous requests.
if (client.status != 200) {
throw new Error(`Got something other than a 200 response. ` +
`client.status: ${client.status}`);
}
}, path, entry => {
invariants.assert_connection_reused(entry);
// Make the first request before calling 'attribute_test' so that only the
// second request's PerformanceResourceTiming entry will be interrogated. We
// don't check the first request's PerformanceResourceTiming entry because
// that's not what this test is trying to validate.
const client = new XMLHttpRequest();
const identifier = Math.random();
path = `${path}?tag=${identifier}`;
client.open("GET", path, false);
client.send();

// The entry must also follow the specification for any entry corresponding
// to a 'typical' 200 Ok response.
if (self.location.protocol == 'https:') {
invariants.assert_tao_pass_no_redirect_https(entry);
} else {
invariants.assert_tao_pass_no_redirect_http(entry);
}
},
"PerformanceResrouceTiming entries need to conform to the spec when a " +
"distinct resource is fetched over a persistent connection");
attribute_test(
async () => {
client.open("GET", path + "&same_resource=false", false);
client.send();

attribute_test(
async () => {
client.open("GET", path, false);
client.setRequestHeader("If-None-Match", identifier);
client.send();
// We expect to get a 200 Ok response because we've requested a different
// resource than previous requests.
if (client.status != 200) {
throw new Error(`Got something other than a 200 response. ` +
`client.status: ${client.status}`);
}
}, path, entry => {
invariants.assert_connection_reused(entry);
on_200(entry);
},
`PerformanceResrouceTiming entries need to conform to the spec when a ` +
`distinct resource is fetched over a persistent connection ` +
`(${test_label})`);

// We expect to get a 304 Not Modified response because we've used a
// matching 'identifier' for the If-None-Match header.
if (client.status != 304) {
throw new Error(`Got something other than a 304 response. ` +
`client.status: ${client.status}`);
}
}, path, entry => {
invariants.assert_connection_reused(entry);
attribute_test(
async () => {
client.open("GET", path, false);
client.setRequestHeader("If-None-Match", identifier);
client.send();

// The entry must also follow the specification for any entry corresponding
// to a 'typical' 304 Not Modified response.
if (self.location.protocol == 'https:') {
invariants.assert_tao_pass_304_not_modified_https(entry);
} else {
invariants.assert_tao_pass_304_not_modified_http(entry);
}
},
"PerformanceResrouceTiming entries need to conform to the spec when the " +
"resource is cache-revalidated over a persistent connection");
// We expect to get a 304 Not Modified response because we've used a
// matching 'identifier' for the If-None-Match header.
if (client.status != 304) {
throw new Error(`Got something other than a 304 response. ` +
`client.status: ${client.status}, response: ` +
`'${client.responseText}'`);
}
}, path, entry => {
invariants.assert_connection_reused(entry);
on_304(entry);
},
`PerformanceResrouceTiming entries need to conform to the spec when the ` +
`resource is cache-revalidated over a persistent connection ` +
`(${test_label})`);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# /xhr/resources/conditional.py -- to fake a 304 response

def main(request, response):
if request.method == "OPTIONS":
# Assume this is a CORS preflight
response.headers.set(b"Access-Control-Allow-Headers", "*")
response.headers.set(b"Access-Control-Allow-Origin", "*")
response.status = (204, "No Content")
return b""
tag = request.GET.first(b"tag", None)
redirect = request.GET.first(b"redirect", None)
match = request.headers.get(b"If-None-Match", None)
Expand Down

0 comments on commit 2ea4ed2

Please sign in to comment.