// test bug 1355539. // // Summary: // Transactions in one pending queue are splited into two groups: // [(Blocking Group)|(Non Blocking Group)] // In each group, the transactions are ordered by its priority. // This test will check if the transaction's order in pending queue is correct. // // Test step: // 1. Create 6 dummy http requests. Server would not process responses until get // all 6 requests. // 2. Once server receive 6 dummy requests, create another 6 http requests with the // defined priority and class flag in |transactionQueue|. // 3. Server starts to process the 6 dummy http requests, so the client can start to // process the pending queue. Server will queue those http requests and put them in // |responseQueue|. // 4. When the server receive all 6 requests, check if the order in |responseQueue| is // equal to |transactionQueue| by comparing the value of X-ID. "use strict"; const { HttpServer } = ChromeUtils.importESModule( "resource://testing-common/httpd.sys.mjs" ); var server = new HttpServer(); server.start(-1); var baseURL = "http://localhost:" + server.identity.primaryPort + "/"; var maxConnections = 0; var debug = false; var dummyResponseQueue = []; var responseQueue = []; function log(msg) { if (!debug) { return; } if (msg) { dump("TEST INFO | " + msg + "\n"); } } function make_channel(url) { var request = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true, }); request.QueryInterface(Ci.nsIHttpChannel); return request; } function serverStopListener() { server.stop(); } function createHttpRequest(requestId, priority, isBlocking, callback) { let uri = baseURL; var chan = make_channel(uri); var listner = new HttpResponseListener(requestId, callback); chan.setRequestHeader("X-ID", requestId, false); chan.setRequestHeader("Cache-control", "no-store", false); chan.QueryInterface(Ci.nsISupportsPriority).priority = priority; if (isBlocking) { var cos = chan.QueryInterface(Ci.nsIClassOfService); cos.addClassFlags(Ci.nsIClassOfService.Leader); } chan.asyncOpen(listner); log("Create http request id=" + requestId); } function setup_dummyHttpRequests(callback) { log("setup_dummyHttpRequests"); for (var i = 0; i < maxConnections; i++) { createHttpRequest(i, i, false, callback); do_test_pending(); } } var transactionQueue = [ { requestId: 101, priority: Ci.nsISupportsPriority.PRIORITY_HIGH, isBlocking: true, }, { requestId: 102, priority: Ci.nsISupportsPriority.PRIORITY_NORMAL, isBlocking: true, }, { requestId: 103, priority: Ci.nsISupportsPriority.PRIORITY_LOW, isBlocking: true, }, { requestId: 104, priority: Ci.nsISupportsPriority.PRIORITY_HIGH, isBlocking: false, }, { requestId: 105, priority: Ci.nsISupportsPriority.PRIORITY_NORMAL, isBlocking: false, }, { requestId: 106, priority: Ci.nsISupportsPriority.PRIORITY_LOW, isBlocking: false, }, ]; function setup_HttpRequests() { log("setup_HttpRequests"); // Create channels in reverse order for (var i = transactionQueue.length - 1; i > -1; ) { var e = transactionQueue[i]; createHttpRequest(e.requestId, e.priority, e.isBlocking); do_test_pending(); --i; } } function check_response_id(responses) { for (var i = 0; i < responses.length; i++) { var id = responses[i].getHeader("X-ID"); Assert.equal(id, transactionQueue[i].requestId); } } function HttpResponseListener(id, onStopCallback) { this.id = id; this.stopCallback = onStopCallback; } HttpResponseListener.prototype = { onStartRequest() {}, onDataAvailable() {}, onStopRequest() { log("STOP id=" + this.id); do_test_finished(); if (this.stopCallback) { this.stopCallback(); } }, }; function setup_http_server() { log("setup_http_server"); maxConnections = Services.prefs.getIntPref( "network.http.max-persistent-connections-per-server" ); var allDummyHttpRequestReceived = false; // Start server; will be stopped at test cleanup time. server.registerPathHandler("/", function (metadata, response) { var id = metadata.getHeader("X-ID"); log("Server recived the response id=" + id); response.processAsync(); response.setHeader("X-ID", id); if (!allDummyHttpRequestReceived) { dummyResponseQueue.push(response); } else { responseQueue.push(response); } if (dummyResponseQueue.length == maxConnections) { log("received all dummy http requets"); allDummyHttpRequestReceived = true; setup_HttpRequests(); processDummyResponse(); } else if (responseQueue.length == maxConnections) { log("received all http requets"); check_response_id(responseQueue); processResponses(); } }); registerCleanupFunction(function () { server.stop(serverStopListener); }); } function processDummyResponse() { if (!dummyResponseQueue.length) { return; } var resposne = dummyResponseQueue.pop(); resposne.finish(); } function processResponses() { while (responseQueue.length) { var resposne = responseQueue.pop(); resposne.finish(); } } function run_test() { setup_http_server(); setup_dummyHttpRequests(processDummyResponse); }