09aff2a77284338c6821967edcda15d8d8897bc4
[WebKit-https.git] / LayoutTests / imported / w3c / web-platform-tests / resource-timing / resources / rt-utilities.sub.js
1 let global = this;
2
3 function hasNecessaryPerformanceFeatures() {
4     return !!(global.PerformanceObserver && global.PerformanceResourceTiming);
5 }
6
7 function testNecessaryPerformanceFeatures() {
8     let supported = hasNecessaryPerformanceFeatures();
9
10     test(function() {
11         assert_true(supported);
12     }, "Must have PerformanceObserver and PerformanceResourceTiming in " + global.constructor.name);
13
14     return supported;
15 }
16
17 function wait() {
18     let now = performance.now();
19     while (now === performance.now())
20         continue;
21 }
22
23 function uniqueDataURL(key, crossOrigin) { return uniqueURL(key, crossOrigin, "resource-timing/resources/data.json"); }
24 function uniqueImageURL(key, crossOrigin) { return uniqueURL(key, crossOrigin, "resource-timing/resources/resource_timing_test0.png"); }
25 function uniqueScriptURL(key, crossOrigin) { return uniqueURL(key, crossOrigin, "resource-timing/resources/resource_timing_test0.js"); }
26 function uniqueStylesheetURL(key, crossOrigin) { return uniqueURL(key, crossOrigin, "resource-timing/resources/resource_timing_test0.css"); }
27 function uniqueDocumentURL(key, crossOrigin) { return uniqueURL(key, crossOrigin, "resource-timing/resources/resource_timing_test0.html"); }
28 function uniqueEventSourceURL(key, crossOrigin) { return uniqueURL(key, crossOrigin, "resource-timing/resources/rt-event-stream.py"); }
29 function uniqueURL(key, crossOrigin, path) {
30     let params = key ? `${key}&${Math.random()}` : `${Math.random()}`;
31     if (crossOrigin === "cross-origin")
32         return `http://{{host}}:{{ports[http][1]}}/${path}?${params}`;
33     return location.origin + `/${path}?${params}`;
34 }
35
36 function crossOriginURL(key, path) {
37     return `http://{{host}}:{{ports[http][1]}}/${path}?${key}`;
38 }
39
40 function urlWithRedirectTo(url) {
41     return `/common/redirect.py?location=${encodeURIComponent(url)}`;
42 }
43
44 function addPipeHeaders(url, headers) {
45     return `${url}&pipe=${headers.join("|")}`;
46 }
47
48 function addTimingAllowOriginHeader(url, origin) {
49     if (!origin) throw `Invalid origin: ${origin}`;
50     return addPipeHeaders(url, [
51         `header(Access-Control-Allow-Origin,*)`,
52         `header(Timing-Allow-Origin,${origin})`,
53     ]);
54 }
55
56 function addMultipleTimingAllowOriginHeaders(url, origins) {
57     if (origins.length < 2) throw "Needs >1 origins";
58     let allHeaders = [`header(Access-Control-Allow-Origin,*)`];
59     allHeaders = allHeaders.concat(origins.map((origin) => `header(Timing-Allow-Origin,${origin},True)`));
60     return addPipeHeaders(url, allHeaders);
61 }
62
63 function addCommaSeparatedTimingAllowOriginHeaders(url, origins) {
64     if (origins.length < 2) throw "Needs >1 origins";
65     return addPipeHeaders(url, [
66         `header(Access-Control-Allow-Origin,*)`,
67         `header(Timing-Allow-Origin,${origins.join("\\,")})`
68     ]);
69 }
70
71 function observeResources(n) {
72     return new Promise(function(resolve, reject) {
73         let entries = [];
74         let observer = new PerformanceObserver(function(list) {
75             entries = entries.concat(list.getEntries());
76             if (entries.length < n)
77                 return;
78             if (entries.length > n)
79                 entries = entries.slice(0, n);
80             observer.disconnect();
81             resolve(entries);
82         });
83         observer.observe({entryTypes: ["resource"]});
84     });
85 }
86
87 function loadResources(n) {
88     let observePromise = observeResources(n);
89     for (let i = 0; i < n; ++i)
90         fetch(uniqueDataURL());
91     return observePromise;
92 }
93
94 function restoreEnvironmentToCleanState() {
95     performance.clearResourceTimings();
96     performance.setResourceTimingBufferSize(200);
97     performance.onresourcetimingbufferfull = null;
98
99     assert_equals(performance.getEntriesByType("resource").length, 0, "context should have no resources");
100 }
101
102 function checkResourceTimingEntryType(entry, expected) {
103     assert_true(entry instanceof PerformanceResourceTiming, "entry should be a PerformanceResourceTiming instance");
104     assert_equals(entry.entryType, "resource", "entryType should be 'resource'");
105
106     if (expected.name)
107         assert_equals(entry.name, expected.name, "name should be the url");
108     if (expected.initiatorType)
109         assert_equals(entry.initiatorType, expected.initiatorType, `initiatorType should be '${expected.initiatorType}'`);
110 }
111
112 function checkResourceTimingEntryTiming(entry) {
113     assert_true(entry instanceof PerformanceResourceTiming, "entry should be a PerformanceResourceTiming instance");
114     assert_equals(entry.entryType, "resource", "entryType should be 'resource'");
115
116     assert_equals(entry.workerStart, 0, "entry should not have a workerStart time");
117     assert_equals(entry.redirectStart, 0, "entry should not have a redirectStart time");
118     assert_equals(entry.redirectEnd, 0, "entry should not have a redirectEnd time");
119     assert_equals(entry.secureConnectionStart, 0, "entry should not have a secureConnectionStart time");
120
121     assert_not_equals(entry.startTime, 0, "entry should have a non-0 fetchStart time");
122     assert_not_equals(entry.fetchStart, 0, "entry should have a non-0 startTime time");
123     assert_equals(entry.startTime, entry.fetchStart, "entry startTime should be the same as fetchTime for non-redirect");
124     assert_greater_than_equal(entry.domainLookupStart, entry.fetchStart, "domainLookupStart after fetchStart");
125     assert_greater_than_equal(entry.domainLookupEnd, entry.domainLookupStart, "domainLookupEnd after domainLookupStart");
126     assert_greater_than_equal(entry.connectStart, entry.domainLookupEnd, "connectStart after domainLookupEnd");
127     assert_greater_than_equal(entry.connectEnd, entry.connectStart, "connectEnd after connectStart");
128     assert_greater_than_equal(entry.requestStart, entry.connectEnd, "requestStart after connectEnd");
129     assert_greater_than_equal(entry.responseStart, entry.requestStart, "responseStart after requestStart");
130     assert_greater_than_equal(entry.responseEnd, entry.responseStart, "responseEnd after responseStart");
131 }
132
133 function resource_entry_type_test({name, url, initiatorType, generateResource}) {
134     let entry = null;
135
136     // Test type attributes.
137     promise_test(function(t) {
138         let promise = observeResources(1).then(function([observedEntry]) {
139             entry = observedEntry;
140             checkResourceTimingEntryType(entry, {name: url, initiatorType});
141         });
142         generateResource(url);
143         return promise;
144     }, "Type: " + name, {timeout: 3000});
145
146     // Test timing attributes.
147     promise_test(function(t) {        
148         assert_true(entry !== null, "previous test should have produced an entry");
149         checkResourceTimingEntryTiming(entry);
150         return Promise.resolve(true);
151     }, "Timing: " + name);
152 }