test_bug1355539_http1.js (5307B)
1 // test bug 1355539. 2 // 3 // Summary: 4 // Transactions in one pending queue are splited into two groups: 5 // [(Blocking Group)|(Non Blocking Group)] 6 // In each group, the transactions are ordered by its priority. 7 // This test will check if the transaction's order in pending queue is correct. 8 // 9 // Test step: 10 // 1. Create 6 dummy http requests. Server would not process responses until get 11 // all 6 requests. 12 // 2. Once server receive 6 dummy requests, create another 6 http requests with the 13 // defined priority and class flag in |transactionQueue|. 14 // 3. Server starts to process the 6 dummy http requests, so the client can start to 15 // process the pending queue. Server will queue those http requests and put them in 16 // |responseQueue|. 17 // 4. When the server receive all 6 requests, check if the order in |responseQueue| is 18 // equal to |transactionQueue| by comparing the value of X-ID. 19 20 "use strict"; 21 22 const { HttpServer } = ChromeUtils.importESModule( 23 "resource://testing-common/httpd.sys.mjs" 24 ); 25 26 var server = new HttpServer(); 27 server.start(-1); 28 var baseURL = "http://localhost:" + server.identity.primaryPort + "/"; 29 var maxConnections = 0; 30 var debug = false; 31 var dummyResponseQueue = []; 32 var responseQueue = []; 33 34 function log(msg) { 35 if (!debug) { 36 return; 37 } 38 39 if (msg) { 40 dump("TEST INFO | " + msg + "\n"); 41 } 42 } 43 44 function make_channel(url) { 45 var request = NetUtil.newChannel({ 46 uri: url, 47 loadUsingSystemPrincipal: true, 48 }); 49 request.QueryInterface(Ci.nsIHttpChannel); 50 return request; 51 } 52 53 function serverStopListener() { 54 server.stop(); 55 } 56 57 function createHttpRequest(requestId, priority, isBlocking, callback) { 58 let uri = baseURL; 59 var chan = make_channel(uri); 60 var listner = new HttpResponseListener(requestId, callback); 61 chan.setRequestHeader("X-ID", requestId, false); 62 chan.setRequestHeader("Cache-control", "no-store", false); 63 chan.QueryInterface(Ci.nsISupportsPriority).priority = priority; 64 if (isBlocking) { 65 var cos = chan.QueryInterface(Ci.nsIClassOfService); 66 cos.addClassFlags(Ci.nsIClassOfService.Leader); 67 } 68 chan.asyncOpen(listner); 69 log("Create http request id=" + requestId); 70 } 71 72 function setup_dummyHttpRequests(callback) { 73 log("setup_dummyHttpRequests"); 74 for (var i = 0; i < maxConnections; i++) { 75 createHttpRequest(i, i, false, callback); 76 do_test_pending(); 77 } 78 } 79 80 var transactionQueue = [ 81 { 82 requestId: 101, 83 priority: Ci.nsISupportsPriority.PRIORITY_HIGH, 84 isBlocking: true, 85 }, 86 { 87 requestId: 102, 88 priority: Ci.nsISupportsPriority.PRIORITY_NORMAL, 89 isBlocking: true, 90 }, 91 { 92 requestId: 103, 93 priority: Ci.nsISupportsPriority.PRIORITY_LOW, 94 isBlocking: true, 95 }, 96 { 97 requestId: 104, 98 priority: Ci.nsISupportsPriority.PRIORITY_HIGH, 99 isBlocking: false, 100 }, 101 { 102 requestId: 105, 103 priority: Ci.nsISupportsPriority.PRIORITY_NORMAL, 104 isBlocking: false, 105 }, 106 { 107 requestId: 106, 108 priority: Ci.nsISupportsPriority.PRIORITY_LOW, 109 isBlocking: false, 110 }, 111 ]; 112 113 function setup_HttpRequests() { 114 log("setup_HttpRequests"); 115 // Create channels in reverse order 116 for (var i = transactionQueue.length - 1; i > -1; ) { 117 var e = transactionQueue[i]; 118 createHttpRequest(e.requestId, e.priority, e.isBlocking); 119 do_test_pending(); 120 --i; 121 } 122 } 123 124 function check_response_id(responses) { 125 for (var i = 0; i < responses.length; i++) { 126 var id = responses[i].getHeader("X-ID"); 127 Assert.equal(id, transactionQueue[i].requestId); 128 } 129 } 130 131 function HttpResponseListener(id, onStopCallback) { 132 this.id = id; 133 this.stopCallback = onStopCallback; 134 } 135 136 HttpResponseListener.prototype = { 137 onStartRequest() {}, 138 139 onDataAvailable() {}, 140 141 onStopRequest() { 142 log("STOP id=" + this.id); 143 do_test_finished(); 144 if (this.stopCallback) { 145 this.stopCallback(); 146 } 147 }, 148 }; 149 150 function setup_http_server() { 151 log("setup_http_server"); 152 maxConnections = Services.prefs.getIntPref( 153 "network.http.max-persistent-connections-per-server" 154 ); 155 156 var allDummyHttpRequestReceived = false; 157 // Start server; will be stopped at test cleanup time. 158 server.registerPathHandler("/", function (metadata, response) { 159 var id = metadata.getHeader("X-ID"); 160 log("Server recived the response id=" + id); 161 162 response.processAsync(); 163 response.setHeader("X-ID", id); 164 165 if (!allDummyHttpRequestReceived) { 166 dummyResponseQueue.push(response); 167 } else { 168 responseQueue.push(response); 169 } 170 171 if (dummyResponseQueue.length == maxConnections) { 172 log("received all dummy http requets"); 173 allDummyHttpRequestReceived = true; 174 setup_HttpRequests(); 175 processDummyResponse(); 176 } else if (responseQueue.length == maxConnections) { 177 log("received all http requets"); 178 check_response_id(responseQueue); 179 processResponses(); 180 } 181 }); 182 183 registerCleanupFunction(function () { 184 server.stop(serverStopListener); 185 }); 186 } 187 188 function processDummyResponse() { 189 if (!dummyResponseQueue.length) { 190 return; 191 } 192 var resposne = dummyResponseQueue.pop(); 193 resposne.finish(); 194 } 195 196 function processResponses() { 197 while (responseQueue.length) { 198 var resposne = responseQueue.pop(); 199 resposne.finish(); 200 } 201 } 202 203 function run_test() { 204 setup_http_server(); 205 setup_dummyHttpRequests(processDummyResponse); 206 }