1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/test/unit/test_seer.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,288 @@ 1.4 +var Cc = Components.classes; 1.5 +var Ci = Components.interfaces; 1.6 +var Cu = Components.utils; 1.7 +var Cr = Components.results; 1.8 + 1.9 +Cu.import("resource://gre/modules/Services.jsm"); 1.10 +Cu.import("resource://gre/modules/FileUtils.jsm"); 1.11 + 1.12 +var seer = null; 1.13 +var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); 1.14 +var profile = null; 1.15 + 1.16 +function extract_origin(uri) { 1.17 + var o = uri.scheme + "://" + uri.asciiHost; 1.18 + if (uri.port !== -1) { 1.19 + o = o + ":" + uri.port; 1.20 + } 1.21 + return o; 1.22 +} 1.23 + 1.24 +var LoadContext = function _loadContext() { 1.25 +}; 1.26 + 1.27 +LoadContext.prototype = { 1.28 + usePrivateBrowsing: false, 1.29 + 1.30 + getInterface: function loadContext_getInterface(iid) { 1.31 + return this.QueryInterface(iid); 1.32 + }, 1.33 + 1.34 + QueryInterface: function loadContext_QueryInterface(iid) { 1.35 + if (iid.equals(Ci.nsINetworkSeerVerifier) || 1.36 + iid.equals(Ci.nsILoadContext)) { 1.37 + return this; 1.38 + } 1.39 + 1.40 + throw Cr.NS_ERROR_NO_INTERFACE; 1.41 + } 1.42 +}; 1.43 + 1.44 +var load_context = new LoadContext(); 1.45 + 1.46 +var Verifier = function _verifier(testing, expected_preconnects, expected_preresolves) { 1.47 + this.verifying = testing; 1.48 + this.expected_preconnects = expected_preconnects; 1.49 + this.expected_preresolves = expected_preresolves; 1.50 +}; 1.51 + 1.52 +Verifier.prototype = { 1.53 + verifying: null, 1.54 + expected_preconnects: null, 1.55 + expected_preresolves: null, 1.56 + 1.57 + getInterface: function verifier_getInterface(iid) { 1.58 + return this.QueryInterface(iid); 1.59 + }, 1.60 + 1.61 + QueryInterface: function verifier_QueryInterface(iid) { 1.62 + if (iid.equals(Ci.nsINetworkSeerVerifier) || 1.63 + iid.equals(Ci.nsISupports)) { 1.64 + return this; 1.65 + } 1.66 + 1.67 + throw Cr.NS_ERROR_NO_INTERFACE; 1.68 + }, 1.69 + 1.70 + maybe_run_next_test: function verifier_maybe_run_next_test() { 1.71 + if (this.expected_preconnects.length === 0 && 1.72 + this.expected_preresolves.length === 0) { 1.73 + do_check_true(true, "Well this is unexpected..."); 1.74 + run_next_test(); 1.75 + } 1.76 + }, 1.77 + 1.78 + onPredictPreconnect: function verifier_onPredictPreconnect(uri) { 1.79 + var origin = extract_origin(uri); 1.80 + var index = this.expected_preconnects.indexOf(origin); 1.81 + if (index == -1) { 1.82 + do_check_true(false, "Got preconnect for unexpected uri " + origin); 1.83 + } else { 1.84 + this.expected_preconnects.splice(index, 1); 1.85 + } 1.86 + this.maybe_run_next_test(); 1.87 + }, 1.88 + 1.89 + onPredictDNS: function verifier_onPredictDNS(uri) { 1.90 + var origin = extract_origin(uri); 1.91 + var index = this.expected_preresolves.indexOf(origin); 1.92 + if (index == -1) { 1.93 + do_check_true(false, "Got preresolve for unexpected uri " + origin); 1.94 + } else { 1.95 + this.expected_preresolves.splice(index, 1); 1.96 + } 1.97 + this.maybe_run_next_test(); 1.98 + } 1.99 +}; 1.100 + 1.101 +function reset_seer() { 1.102 + seer.reset(); 1.103 +} 1.104 + 1.105 +function newURI(s) { 1.106 + return ios.newURI(s, null, null); 1.107 +} 1.108 + 1.109 +function test_link_hover() { 1.110 + reset_seer(); 1.111 + var uri = newURI("http://localhost:4444/foo/bar"); 1.112 + var referrer = newURI("http://localhost:4444/foo"); 1.113 + var preconns = ["http://localhost:4444"]; 1.114 + 1.115 + var verifier = new Verifier("hover", preconns, []); 1.116 + seer.predict(uri, referrer, seer.PREDICT_LINK, load_context, verifier); 1.117 +} 1.118 + 1.119 +function test_pageload() { 1.120 + reset_seer(); 1.121 + var toplevel = "http://localhost:4444/index.html"; 1.122 + var subresources = [ 1.123 + "http://localhost:4444/style.css", 1.124 + "http://localhost:4443/jquery.js", 1.125 + "http://localhost:4444/image.png" 1.126 + ]; 1.127 + 1.128 + var tluri = newURI(toplevel); 1.129 + seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); 1.130 + var preconns = []; 1.131 + for (var i = 0; i < subresources.length; i++) { 1.132 + var sruri = newURI(subresources[i]); 1.133 + seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); 1.134 + preconns.push(extract_origin(sruri)); 1.135 + } 1.136 + 1.137 + var verifier = new Verifier("pageload", preconns, []); 1.138 + seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, verifier); 1.139 +} 1.140 + 1.141 +function test_redirect() { 1.142 + reset_seer(); 1.143 + var initial = "http://localhost:4443/redirect"; 1.144 + var target = "http://localhost:4444/index.html"; 1.145 + var subresources = [ 1.146 + "http://localhost:4444/style.css", 1.147 + "http://localhost:4443/jquery.js", 1.148 + "http://localhost:4444/image.png" 1.149 + ]; 1.150 + 1.151 + var inituri = newURI(initial); 1.152 + var targeturi = newURI(target); 1.153 + seer.learn(inituri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); 1.154 + seer.learn(targeturi, inituri, seer.LEARN_LOAD_REDIRECT, load_context); 1.155 + seer.learn(targeturi, null, seer.LEARN_LOAD_TOPLEVEL, load_context); 1.156 + 1.157 + var preconns = []; 1.158 + preconns.push(extract_origin(targeturi)); 1.159 + for (var i = 0; i < subresources.length; i++) { 1.160 + var sruri = newURI(subresources[i]); 1.161 + seer.learn(sruri, targeturi, seer.LEARN_LOAD_SUBRESOURCE, load_context); 1.162 + preconns.push(extract_origin(sruri)); 1.163 + } 1.164 + 1.165 + var verifier = new Verifier("redirect", preconns, []); 1.166 + seer.predict(inituri, null, seer.PREDICT_LOAD, load_context, verifier); 1.167 +} 1.168 + 1.169 +function test_startup() { 1.170 + reset_seer(); 1.171 + var uris = [ 1.172 + "http://localhost:4444/startup", 1.173 + "http://localhost:4443/startup" 1.174 + ]; 1.175 + var preconns = []; 1.176 + for (var i = 0; i < uris.length; i++) { 1.177 + var uri = newURI(uris[i]); 1.178 + seer.learn(uri, null, seer.LEARN_STARTUP, load_context); 1.179 + preconns.push(extract_origin(uri)); 1.180 + } 1.181 + 1.182 + var verifier = new Verifier("startup", preconns, []); 1.183 + seer.predict(null, null, seer.PREDICT_STARTUP, load_context, verifier); 1.184 +} 1.185 + 1.186 +// A class used to guarantee serialization of SQL queries so we can properly 1.187 +// update last hit times on subresources to ensure the seer tries to do DNS 1.188 +// preresolve on them instead of preconnecting 1.189 +var DnsContinueVerifier = function _dnsContinueVerifier(subresource, tluri, preresolves) { 1.190 + this.subresource = subresource; 1.191 + this.tluri = tluri; 1.192 + this.preresolves = preresolves; 1.193 +}; 1.194 + 1.195 +DnsContinueVerifier.prototype = { 1.196 + subresource: null, 1.197 + tluri: null, 1.198 + preresolves: null, 1.199 + 1.200 + getInterface: function _dnsContinueVerifier_getInterface(iid) { 1.201 + return this.QueryInterface(iid); 1.202 + }, 1.203 + 1.204 + QueryInterface: function _dnsContinueVerifier_QueryInterface(iid) { 1.205 + if (iid.equals(Ci.nsISupports) || 1.206 + iid.equals(Ci.nsINetworkSeerVerifier)) { 1.207 + return this; 1.208 + } 1.209 + 1.210 + throw Cr.NS_ERROR_NO_INTERFACE; 1.211 + }, 1.212 + 1.213 + onPredictPreconnect: function _dnsContinueVerifier_onPredictPreconnect() { 1.214 + // This means that the seer has learned and done our "checkpoint" prediction 1.215 + // Now we can get on with the prediction we actually want to test 1.216 + 1.217 + // tstamp is 10 days older than now - just over 1 week, which will ensure we 1.218 + // hit our cutoff for dns vs. preconnect. This is all in usec, hence the 1.219 + // x1000 on the Date object value. 1.220 + var tstamp = (new Date().valueOf() * 1000) - (10 * 86400 * 1000000); 1.221 + 1.222 + seer.prepareForDnsTest(tstamp, this.subresource); 1.223 + 1.224 + var verifier = new Verifier("dns", [], this.preresolves); 1.225 + seer.predict(this.tluri, null, seer.PREDICT_LOAD, load_context, verifier); 1.226 + }, 1.227 + 1.228 + onPredictDNS: function _dnsContinueVerifier_onPredictDNS() { 1.229 + do_check_true(false, "Shouldn't have gotten a preresolve prediction here!"); 1.230 + } 1.231 +}; 1.232 + 1.233 +function test_dns() { 1.234 + reset_seer(); 1.235 + var toplevel = "http://localhost:4444/index.html"; 1.236 + var subresource = "http://localhost:4443/jquery.js"; 1.237 + 1.238 + var tluri = newURI(toplevel); 1.239 + seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); 1.240 + var sruri = newURI(subresource); 1.241 + seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); 1.242 + 1.243 + var preresolves = [extract_origin(sruri)]; 1.244 + var continue_verifier = new DnsContinueVerifier(subresource, tluri, preresolves); 1.245 + // Fire off a prediction that will do preconnects so we know when the seer 1.246 + // thread has gotten to the point where we can update the database manually 1.247 + seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, continue_verifier); 1.248 +} 1.249 + 1.250 +function test_origin() { 1.251 + reset_seer(); 1.252 + var toplevel = "http://localhost:4444/index.html"; 1.253 + var subresources = [ 1.254 + "http://localhost:4444/style.css", 1.255 + "http://localhost:4443/jquery.js", 1.256 + "http://localhost:4444/image.png" 1.257 + ]; 1.258 + 1.259 + var tluri = newURI(toplevel); 1.260 + seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); 1.261 + var preconns = []; 1.262 + for (var i = 0; i < subresources.length; i++) { 1.263 + var sruri = newURI(subresources[i]); 1.264 + seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); 1.265 + var origin = extract_origin(sruri); 1.266 + if (preconns.indexOf(origin) === -1) { 1.267 + preconns.push(origin); 1.268 + } 1.269 + } 1.270 + 1.271 + var loaduri = newURI("http://localhost:4444/anotherpage.html"); 1.272 + var verifier = new Verifier("origin", preconns, []); 1.273 + seer.predict(loaduri, null, seer.PREDICT_LOAD, load_context, verifier); 1.274 +} 1.275 + 1.276 +var tests = [ 1.277 + test_link_hover, 1.278 + test_pageload, 1.279 + test_redirect, 1.280 + test_startup, 1.281 + test_dns, 1.282 + test_origin 1.283 +]; 1.284 + 1.285 +function run_test() { 1.286 + tests.forEach(add_test); 1.287 + profile = do_get_profile(); 1.288 + seer = Cc["@mozilla.org/network/seer;1"].getService(Ci.nsINetworkSeer); 1.289 + do_register_cleanup(reset_seer); 1.290 + run_next_test(); 1.291 +}