test_resource_timing.js (9464B)
1 var TEST_ALLOWED_TIMING_DELTA = 20; 2 3 var waitTimer; 4 var expectedEntries = {}; 5 6 var initiatorTypes = ["iframe", "img", "link", "script", "xmlhttprequest"]; 7 8 var tests = {}; 9 setup(function() { 10 for (var i in initiatorTypes) { 11 var type = initiatorTypes[i]; 12 tests[type] = { 13 "entry": async_test("window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (" + type + ")"), 14 "simple_attrs": async_test("PerformanceEntry has correct name, initiatorType, startTime, and duration (" + type + ")"), 15 "timing_attrs": async_test("PerformanceEntry has correct order of timing attributes (" + type + ")"), 16 "network_attrs": async_test("PerformanceEntry has correct network transfer attributes (" + type + ")"), 17 "protocol": async_test("PerformanceEntry has correct protocol attribute (" + type + ")") 18 }; 19 } 20 }); 21 22 function resolve(path) { 23 var a = document.createElement("a"); 24 a.href = path; 25 return a.href; 26 } 27 28 onload = function() 29 { 30 // check that the Performance Timeline API exists 31 test(function() { 32 assert_idl_attribute(window.performance, "getEntriesByName", 33 "window.performance.getEntriesByName() is defined"); 34 }); 35 test(function() { 36 assert_idl_attribute(window.performance, "getEntriesByType", 37 "window.performance.getEntriesByType() is defined"); 38 }); 39 test(function() { 40 assert_idl_attribute(window.performance, "getEntries", 41 "window.performance.getEntries() is defined"); 42 }); 43 44 var expected_entry; 45 var url; 46 var type; 47 var startTime; 48 var element; 49 var encodedBodySize; 50 var decodedBodySize; 51 for (var i in initiatorTypes) { 52 startTime = window.performance.now(); 53 type = initiatorTypes[i]; 54 if (type != "xmlhttprequest") { 55 element = document.createElement(type); 56 } else { 57 element = null; 58 } 59 switch (type) { 60 case "iframe": 61 url = resolve("resources/resource_timing_test0.html"); 62 element.src = url; 63 encodedBodySize = 215; 64 decodedBodySize = 215; 65 break; 66 case "img": 67 url = resolve("resources/resource_timing_test0.png"); 68 element.src = url; 69 encodedBodySize = 249; 70 decodedBodySize = 249; 71 break; 72 case "link": 73 element.rel = "stylesheet"; 74 url = resolve("resources/resource_timing_test0.css"); 75 element.href = url; 76 encodedBodySize = 44; 77 decodedBodySize = 44; 78 break; 79 case "script": 80 element.type = "text/javascript"; 81 url = resolve("resources/resource_timing_test0.js"); 82 element.src = url; 83 encodedBodySize = 133; 84 decodedBodySize = 133; 85 break; 86 case "xmlhttprequest": 87 var xmlhttp = new XMLHttpRequest(); 88 url = resolve("resources/gzip_xml.py"); 89 xmlhttp.open('GET', url, true); 90 xmlhttp.send(); 91 encodedBodySize = 112; 92 decodedBodySize = 125; 93 break; 94 } 95 96 expected_entry = {name:url, 97 startTime: startTime, 98 initiatorType: type, 99 encodedBodySize: encodedBodySize, 100 decodedBodySize: decodedBodySize 101 }; 102 103 switch (type) { 104 case "link": 105 poll_for_stylesheet_load(expected_entry); 106 document.body.appendChild(element); 107 break; 108 case "xmlhttprequest": 109 xmlhttp.onload = (function(entry) { 110 return function (event) { 111 resource_load(entry); 112 }; 113 })(expected_entry); 114 break; 115 default: 116 element.onload = (function(entry) { 117 return function (event) { 118 resource_load(entry); 119 }; 120 })(expected_entry); 121 document.body.appendChild(element); 122 } 123 124 } 125 }; 126 127 function poll_for_stylesheet_load(expected_entry) { 128 var t = tests[expected_entry.initiatorType]; 129 130 function inner() { 131 for(var i=0; i<document.styleSheets.length; i++) { 132 var sheet = document.styleSheets[i]; 133 if (sheet.href === expected_entry.name) { 134 try { 135 // try/catch avoids throwing if sheet object exists before it is loaded, 136 // which is a bug, but not what we are trying to test here. 137 var hasRules = sheet.cssRules.length > 0; 138 } catch(e) { 139 hasRules = false; 140 } 141 if (hasRules) { 142 t["entry"].step_timeout(function() { 143 resource_load(expected_entry); 144 }, 200); 145 return; 146 } 147 } 148 } 149 t["entry"].step_timeout(inner, 100); 150 } 151 inner(); 152 } 153 154 function resource_load(expected) 155 { 156 var t = tests[expected.initiatorType]; 157 158 t["entry"].step(function() { 159 var entries_by_name = window.performance.getEntriesByName(expected.name); 160 assert_equals(entries_by_name.length, 1, "should have a single entry for each resource (without type)"); 161 var entries_by_name_type = window.performance.getEntriesByName(expected.name, "resource"); 162 assert_equals(entries_by_name_type.length, 1, "should have a single entry for each resource (with type)"); 163 assert_not_equals(entries_by_name, entries_by_name_type, "values should be copies"); 164 for (p in entries_by_name[0]) { 165 var assertMethod = assert_equals 166 if (Array.isArray(entries_by_name[0][p]) && Array.isArray(entries_by_name_type[0][p])) { 167 assertMethod = assert_array_equals 168 } 169 assertMethod(entries_by_name[0][p], entries_by_name_type[0][p], "Property " + p + " should match"); 170 } 171 this.done(); 172 }); 173 174 t["simple_attrs"].step(function() { 175 var actual = window.performance.getEntriesByName(expected.name)[0]; 176 var expected_type = expected.initiatorType; 177 assert_equals(actual.name, expected.name); 178 assert_equals(actual.initiatorType, expected_type); 179 assert_equals(actual.entryType, "resource"); 180 assert_greater_than_equal(actual.startTime, expected.startTime, "startTime is after the script to initiate the load ran"); 181 assert_equals(actual.duration, (actual.responseEnd - actual.startTime)); 182 this.done(); 183 }); 184 185 t["timing_attrs"].step(function test() { 186 const entries = window.performance.getEntriesByName(expected.name); 187 assert_equals(entries.length, 1, 'There should be a single matching entry'); 188 const actual = entries[0]; 189 if (window.location.protocol == "http:") { 190 assert_equals(actual.secureConnectionStart, 0, 'secureConnectionStart should be 0 in http'); 191 } else { 192 assert_greater_than(actual.secureConnectionStart, 0, 'secureConnectionStart should not be 0 in https'); 193 } 194 195 assert_equals(actual.redirectStart, 0, 'redirectStart should be 0'); 196 assert_equals(actual.redirectEnd, 0, 'redirectEnd should be 0'); 197 assert_equals(actual.fetchStart, actual.startTime, 'fetchStart is equal to startTime'); 198 assert_greater_than_equal(actual.domainLookupStart, actual.fetchStart, 'domainLookupStart after fetchStart'); 199 assert_greater_than_equal(actual.domainLookupEnd, actual.domainLookupStart, 'domainLookupEnd after domainLookupStart'); 200 assert_greater_than_equal(actual.connectStart, actual.domainLookupEnd, 'connectStart after domainLookupEnd'); 201 assert_greater_than_equal(actual.connectEnd, actual.connectStart, 'connectEnd after connectStart'); 202 assert_true(actual.secureConnectionStart == 0 || actual.secureConnectionStart <= actual.requestStart, 203 "secureConnectionStart should be either 0 or smaller than/equals to requestStart") 204 assert_greater_than_equal(actual.requestStart, actual.connectEnd, 'requestStart after connectEnd'); 205 assert_greater_than_equal(actual.responseStart, actual.requestStart, 'responseStart after requestStart'); 206 assert_greater_than_equal(actual.responseEnd, actual.responseStart, 'responseEnd after responseStart'); 207 this.done(); 208 }); 209 210 t["network_attrs"].step(function test() { 211 var actual = window.performance.getEntriesByName(expected.name)[0]; 212 assert_equals(actual.encodedBodySize, expected.encodedBodySize, "encodedBodySize size"); 213 assert_equals(actual.decodedBodySize, expected.decodedBodySize, "decodedBodySize size"); 214 215 // Transfer size will vary from browser to browser based on default headers, etc. This 216 // test verifies that transferSize for uncached resources is greater than on-the-wire 217 // body size. 218 assert_greater_than(actual.transferSize, actual.encodedBodySize, "transferSize size"); 219 this.done(); 220 }); 221 222 t["protocol"].step(function() { 223 var actual = window.performance.getEntriesByName(expected.name)[0]; 224 assert_equals(actual.nextHopProtocol, "http/1.1", "expected protocol"); 225 this.done(); 226 }); 227 228 }