Skip to content

Commit 398c8e1

Browse files
quasi-modchromium-wpt-export-bot
authored andcommitted
Add WPTs for ServiceWorker Static Routing API Resource Timing
This CL adds WPTs for Service Worker Static Routing API Resource Timing. It conducts a set of tests to determine if the resource timing is correctly working on each source type, and on main and sub-resources. Explainer: WICG/service-worker-static-routing-api#25 Bug: 41496865 Change-Id: Ide7d352d4824b9491645964febb6522ffe71aafb
1 parent 48e6484 commit 398c8e1

File tree

1 file changed

+291
-0
lines changed

1 file changed

+291
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
<!DOCTYPE html>
2+
<meta charset="utf-8">
3+
<title>
4+
Static Router: timing information should be shown when used.
5+
</title>
6+
<script src="/common/get-host-info.sub.js"></script>
7+
<script src="/resources/testharness.js"></script>
8+
<script src="/resources/testharnessreport.js"></script>
9+
<script src="resources/test-helpers.sub.js"></script>
10+
<script src="resources/static-router-helpers.sub.js"></script>
11+
<body>
12+
<script>
13+
const ROUTER_RULE_KEY = 'condition-urlpattern-constructed-source-network';
14+
const ROUTER_RULE_KEY_URLPATTERN_CACHE =
15+
'condition-urlpattern-string-source-cache';
16+
const ROUTER_RULE_KEY_REQUEST_CACHE = 'condition-request-navigate-source-cache';
17+
const ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_MATCH_ALL_CACHE =
18+
'condition-urlpattern-constructed-match-all-source-cache';
19+
const REGISTERED_ROUTE = 'resources/direct.txt';
20+
const CACHED_ROUTE = 'resources/cache.txt';
21+
const NON_REGISTERED_ROUTE = 'resources/simple.html';
22+
23+
const RACE_ROUTER_KEY =
24+
'condition-urlpattern-string-source-race-network-and-fetch-handler';
25+
const RACE_SW_SRC = 'resources/static-router-race-network-and-fetch-handler-sw.js';
26+
const RACE_ROUTE = 'resources/direct.py';
27+
28+
const host_info = get_host_info();
29+
const path = new URL(".", window.location).pathname;
30+
31+
function resourceUrl(resource) {
32+
return `${host_info['HTTPS_ORIGIN']}${path}${resource}`;
33+
}
34+
35+
// Verify existance of a PerformanceEntry and the order between the timings of
36+
// ServiceWorker Static routing API.
37+
//
38+
// |options| has these properties:
39+
// performance: Performance interface to verify existance of the entry.
40+
// url: the URL of resource
41+
// description: the description passed to each assertion.
42+
// matched_source: the expected matched source of router evaluation.
43+
// actual_source: the expected actual source used to get the resource.
44+
function test_resource_timing(options) {
45+
const description = options.description;
46+
const entryList = options.performance.getEntriesByName(resourceUrl(options.url));
47+
assert_equals(entryList.length, 1, description);
48+
const entry = entryList[0];
49+
50+
assert_equals(entry.matchedSourceType, options.matched_source_type, description);
51+
assert_equals(entry.finalSourceType, options.final_source_type, description);
52+
53+
assert_greater_than(entry.workerRouterEvaluationStart, 0, description);
54+
switch (entry.matchedSouceType) {
55+
case 'network':
56+
assert_equals(entry.workerStart, 0, description);
57+
assert_equals(entry.workerCacheLookupStart, 0, description);
58+
assert_less_than_equal(entry.workerRouterEvaluationStart, entry.fetchStart, description);
59+
break;
60+
case 'cache':
61+
assert_equals(entry.workerStart, 0, description);
62+
assert_greater_than_equal(entry.workerCacheLookupStart, entry.workerRouterEvaluationStart, description);
63+
if (entry.finalSourceType === 'cache') {
64+
assert_equals(entry.fetchStart, 0, description);
65+
assert_less_than_equal(entry.workerCacheLookupStart, entry.responseStart, description);
66+
} else {
67+
assert_less_than_equal(entry.workerCacheLookupStart, entry.fetchStart, description);
68+
}
69+
break;
70+
case 'race-network-and-fetch':
71+
assert_equals(entry.workerCacheLookupStart, 0, description);
72+
if (entry.finalSourceType === 'network') {
73+
assert_equals(entry.workerStart, 0, description);
74+
assert_less_than_equal(entry.workerRouterEvaluationStart, entry.fetchStart, description);
75+
} else {
76+
assert_greater_than_equal(entry.workerStart, entry.workerRouterEvaluationStart, description);
77+
assert_greater_than_equal(entry.fetchStart, entry.workerStart, description);
78+
}
79+
break;
80+
case 'fetch-event':
81+
case '':
82+
assert_equals(entry.workerCacheLookupStart, 0, description);
83+
assert_greater_than_equal(entry.workerStart, entry.workerRouterEvaluationStart, description);
84+
assert_greater_than_equal(entry.fetchStart, entry.workerStart, description);
85+
break;
86+
}
87+
}
88+
89+
iframeTest(REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin, worker) => {
90+
const {requests} = await get_info_from_worker(worker);
91+
assert_equals(requests.length, 0);
92+
assert_equals(iwin.document.body.innerText, "Network\n");
93+
test_resource_timing({
94+
performance: iwin.performance,
95+
url: REGISTERED_ROUTE,
96+
matched_source_type: 'network',
97+
final_source_type: 'network',
98+
description: "network as source on main resource"
99+
});
100+
}, 'Main resource load matched with the condition and resource timing');
101+
102+
iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin, worker) => {
103+
const {requests} = await get_info_from_worker(worker);
104+
assert_equals(requests.length, 1);
105+
assert_equals(
106+
requests[0].url,
107+
resourceUrl(NON_REGISTERED_ROUTE));
108+
assert_equals(requests[0].mode, 'navigate');
109+
test_resource_timing({
110+
performance: iwin.performance,
111+
url: NON_REGISTERED_ROUTE,
112+
matched_source_type: '',
113+
final_source_type: '',
114+
description: "no rule matched on main resource"
115+
});
116+
}, 'Main resource load not matched with the condition and resource timing');
117+
118+
iframeTest(CACHED_ROUTE, ROUTER_RULE_KEY_URLPATTERN_CACHE, async (t, iwin, worker) => {
119+
const {requests} = await get_info_from_worker(worker);
120+
assert_equals(requests.length, 0);
121+
assert_equals(iwin.document.body.innerText, "From cache");
122+
test_resource_timing({
123+
performance: iwin.performance,
124+
url: CACHED_ROUTE,
125+
matched_source_type: 'cache',
126+
final_source_type: 'cache',
127+
description: "cache as source on main resource and cache hit"
128+
});
129+
}, 'Main resource load matched with the cache source and resource timing');
130+
131+
iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY_REQUEST_CACHE, async (t, iwin, worker) => {
132+
const {requests} = await get_info_from_worker(worker);
133+
// When the request matched to the rule with the "cache" source but failed to
134+
// get the cache entry, the fetch handler is not involved and the network
135+
// fallback is triggered instead.
136+
assert_equals(requests.length, 0);
137+
assert_equals(iwin.document.body.innerText, "Here's a simple html file.");
138+
test_resource_timing({
139+
performance: iwin.performance,
140+
url: NON_REGISTERED_ROUTE,
141+
matched_source_type: 'cache',
142+
final_source_type: 'network',
143+
description: "cache as source on main resource and cache miss, fallback to network"
144+
});
145+
}, 'Main resource fallback to the network when there is no cache entry and resource timing');
146+
147+
// Subresource
148+
iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin) => {
149+
const rnd = randomString();
150+
const subresource = `?nonce=${rnd}`;
151+
const response = await iwin.fetch(subresource);
152+
assert_equals(await response.text(), rnd);
153+
test_resource_timing({
154+
performance: iwin.performance,
155+
url: NON_REGISTERED_ROUTE + subresource,
156+
matched_source_type: '',
157+
final_source_type: '',
158+
description: "no source type matched"
159+
});
160+
}, 'Subresource load not matched with URLPattern condition');
161+
162+
iframeTest(REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin) => {
163+
const rnd = randomString();
164+
const subresource = `?nonce=${rnd}`;
165+
const response = await iwin.fetch(subresource);
166+
assert_equals(await response.text(), "Network\n");
167+
test_resource_timing({
168+
performance: iwin.performance,
169+
url: REGISTERED_ROUTE + subresource,
170+
matched_source_type: 'network',
171+
final_source_type: 'network',
172+
description: "network as source on subresource"
173+
});
174+
}, 'Subresource load matched with URLPattern condition');
175+
176+
iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY_URLPATTERN_CACHE, async (t, iwin) => {
177+
// No need to set `resources/` because the request is dispatched from iframe.
178+
const CACHED_FILE = 'cache.txt';
179+
const response = await iwin.fetch(CACHED_FILE);
180+
assert_equals(await response.text(), "From cache");
181+
test_resource_timing({
182+
performance: iwin.performance,
183+
url: CACHED_ROUTE, // We need a path including `resources/` to get the resource
184+
matched_source_type: 'cache',
185+
final_source_type: 'cache',
186+
description: "cache as source on subresource and cache hits"
187+
});
188+
}, 'Subresource load matched with the cache source rule');
189+
190+
iframeTest(REGISTERED_ROUTE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_MATCH_ALL_CACHE, async (t, iwin, worker) => {
191+
// Send a request, which is not stored in the cache, but it exists over the network.
192+
const rnd = randomString();
193+
let subresource = `?nonce=${rnd}`;
194+
let response = await iwin.fetch(subresource);
195+
assert_equals(await response.text(), "Network\n");
196+
assert_equals(response.status, 200);
197+
198+
// Request is not handled by ServiceWorker.
199+
const {requests} = await get_info_from_worker(worker);
200+
assert_equals(requests.length, 0);
201+
test_resource_timing({
202+
performance: iwin.performance,
203+
url: `${REGISTERED_ROUTE}${subresource}`,
204+
matched_source_type: 'cache',
205+
final_source_type: 'network',
206+
description: "cache as source on subresource and cache misses"
207+
});
208+
}, 'Subresource load did not match with the cache and fallback to the network');
209+
210+
// Race Tests
211+
promise_test(async t => {
212+
const rnd = randomString();
213+
const url = `${RACE_ROUTE}?nonce=${rnd}&server_slow`;
214+
const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
215+
const iframe = await createIframe(t, url);
216+
// Expect the response from the fetch handler.
217+
assert_equals(iframe.contentWindow.document.body.innerText, rnd);
218+
const {requests} = await get_info_from_worker(worker);
219+
assert_equals(requests.length, 1);
220+
test_resource_timing({
221+
performance: iframe.contentWindow.performance,
222+
url: url,
223+
matched_source_type: 'race-network-and-fetch',
224+
final_source_type: 'fetch-event',
225+
description: "race as source on main resource, and fetch-event wins"
226+
});
227+
}, 'Main resource load matched the rule with race-network-and-fetch-handler source, and the fetch handler response is faster than the server response');
228+
229+
promise_test(async t => {
230+
const rnd = randomString();
231+
const url = `${RACE_ROUTE}?nonce=${rnd}&sw_slow`;
232+
const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
233+
const iframe = await createIframe(t, url);
234+
// Expect the response from the netowrk request.
235+
assert_equals(iframe.contentWindow.document.body.innerText, "Network with GET request");
236+
// Ensure the fetch handler is also executed.
237+
const {requests} = await get_info_from_worker(worker);
238+
assert_equals(requests.length, 1);
239+
test_resource_timing({
240+
performance: iframe.contentWindow.performance,
241+
url: url,
242+
matched_source_type: 'race-network-and-fetch',
243+
final_source_type: 'network',
244+
description: "race as source on main resource, and network wins"
245+
});
246+
}, 'Main resource load matched the rule with race-network-and-fetch-handler source, and the server reseponse is faster than the fetch handler');
247+
248+
promise_test(async t => {
249+
const rnd = randomString();
250+
const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
251+
const iframe = await createIframe(t, RACE_ROUTE);
252+
const subresource = `?nonce=${rnd}&server_slow`;
253+
// Expect the response from the fetch handler.
254+
const response = await iframe.contentWindow.fetch(subresource);
255+
assert_equals(response.status, 200);
256+
assert_equals(await response.text(), rnd);
257+
const {requests} = await get_info_from_worker(worker);
258+
assert_equals(requests.length, 2);
259+
260+
test_resource_timing({
261+
performance: iframe.contentWindow.performance,
262+
url: `${RACE_ROUTE}${subresource}`,
263+
matched_source_type: 'race-network-and-fetch',
264+
final_source_type: 'fetch-event',
265+
description: "race as source on subresource and fetch wins"
266+
});
267+
}, 'Subresource load matched the rule with race-network-and-fetch-handler source, and the fetch handler response is faster than the server response');
268+
269+
promise_test(async t => {
270+
const rnd = randomString();
271+
const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
272+
const iframe = await createIframe(t, RACE_ROUTE);
273+
const subresource = `?nonce=${rnd}&sw_slow`;
274+
// Expect the response from the network request.
275+
const response = await iframe.contentWindow.fetch(subresource);
276+
assert_equals(response.status, 200);
277+
assert_equals(await response.text(), "Network with GET request");
278+
// Ensure the fetch handler is also executed.
279+
const {requests} = await get_info_from_worker(worker);
280+
assert_equals(requests.length, 2);
281+
282+
test_resource_timing({
283+
performance: iframe.contentWindow.performance,
284+
url: `${RACE_ROUTE}${subresource}`,
285+
matched_source_type: 'race-network-and-fetch',
286+
final_source_type: 'network',
287+
description: "race as source on subresource and network wins"
288+
});
289+
}, 'Subresource load matched the rule with race-network-and-fetch-handler source, and the server reseponse is faster than the fetch handler');
290+
</script>
291+
</body>

0 commit comments

Comments
 (0)