1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/downloads/test/unit/test_resume.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,138 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/** 1.9 + * Test download resume to do real-resume instead of stalling-the-channel 1.10 + * resume. Also test bug 395537 for resuming files that are deleted before 1.11 + * they're resumed. Bug 398216 is checked by making sure the reported progress 1.12 + * and file size are updated for finished downloads. 1.13 + */ 1.14 + 1.15 +const nsIF = Ci.nsIFile; 1.16 +const nsIDM = Ci.nsIDownloadManager; 1.17 +const nsIWBP = Ci.nsIWebBrowserPersist; 1.18 +const nsIWPL = Ci.nsIWebProgressListener; 1.19 +const dm = Cc["@mozilla.org/download-manager;1"].getService(nsIDM); 1.20 + 1.21 +function run_test() 1.22 +{ 1.23 + if (oldDownloadManagerDisabled()) { 1.24 + return; 1.25 + } 1.26 + 1.27 + /** 1.28 + * 1. Create data for http server to send 1.29 + */ 1.30 + // data starts at 10 bytes 1.31 + var data = "1234567890"; 1.32 + // data * 10^4 = 100,000 bytes (actually 101,111 bytes with newline) 1.33 + for (var i = 0; i < 4; i++) { 1.34 + data = [data,data,data,data,data,data,data,data,data,data,"\n"].join(""); 1.35 + } 1.36 + 1.37 + /** 1.38 + * 2. Start the http server that can handle resume 1.39 + */ 1.40 + var httpserv = new HttpServer(); 1.41 + var didResumeServer = false; 1.42 + httpserv.registerPathHandler("/resume", function(meta, resp) { 1.43 + var body = data; 1.44 + resp.setHeader("Content-Type", "text/html", false); 1.45 + if (meta.hasHeader("Range")) { 1.46 + // track that we resumed for testing 1.47 + didResumeServer = true; 1.48 + // Syntax: bytes=[from]-[to] (we don't support multiple ranges) 1.49 + var matches = meta.getHeader("Range").match(/^\s*bytes=(\d+)?-(\d+)?\s*$/); 1.50 + var from = (matches[1] === undefined) ? 0 : matches[1]; 1.51 + var to = (matches[2] === undefined) ? data.length - 1 : matches[2]; 1.52 + if (from >= data.length) { 1.53 + resp.setStatusLine(meta.httpVersion, 416, "Start pos too high"); 1.54 + resp.setHeader("Content-Range", "*/" + data.length, false); 1.55 + return; 1.56 + } 1.57 + body = body.substring(from, to + 1); 1.58 + // always respond to successful range requests with 206 1.59 + resp.setStatusLine(meta.httpVersion, 206, "Partial Content"); 1.60 + resp.setHeader("Content-Range", from + "-" + to + "/" + data.length, false); 1.61 + } 1.62 + resp.bodyOutputStream.write(body, body.length); 1.63 + }); 1.64 + httpserv.start(-1); 1.65 + 1.66 + /** 1.67 + * 3. Perform various actions for certain download states 1.68 + */ 1.69 + var didPause = false; 1.70 + var didResumeDownload = false; 1.71 + dm.addListener({ 1.72 + onDownloadStateChange: function(a, aDl) { 1.73 + if (aDl.state == nsIDM.DOWNLOAD_DOWNLOADING && !didPause) { 1.74 + /** 1.75 + * (1) queued -> downloading = pause the download 1.76 + */ 1.77 + dm.pauseDownload(aDl.id); 1.78 + } else if (aDl.state == nsIDM.DOWNLOAD_PAUSED) { 1.79 + /** 1.80 + * (2) downloading -> paused = remove the file 1.81 + */ 1.82 + didPause = true; 1.83 + // Test bug 395537 by removing the file before we actually resume 1.84 + aDl.targetFile.remove(false); 1.85 + } else if (aDl.state == nsIDM.DOWNLOAD_FINISHED) { 1.86 + /** 1.87 + * (4) downloading (resumed) -> finished = check tests 1.88 + */ 1.89 + // did we pause at all? 1.90 + do_check_true(didPause); 1.91 + // did we real-resume and not fake-resume? 1.92 + do_check_true(didResumeDownload); 1.93 + // extra real-resume check for the server 1.94 + do_check_true(didResumeServer); 1.95 + // did we download the whole file? 1.96 + do_check_eq(data.length, aDl.targetFile.fileSize); 1.97 + // extra sanity checks on size (test bug 398216) 1.98 + do_check_eq(data.length, aDl.amountTransferred); 1.99 + do_check_eq(data.length, aDl.size); 1.100 + 1.101 + httpserv.stop(do_test_finished); 1.102 + } 1.103 + }, 1.104 + onStateChange: function(a, b, aState, d, aDl) { 1.105 + if ((aState & nsIWPL.STATE_STOP) && didPause && !didResumeServer && 1.106 + !didResumeDownload) { 1.107 + /** 1.108 + * (3) paused -> stopped = resume the download 1.109 + */ 1.110 + dm.resumeDownload(aDl.id); 1.111 + didResumeDownload = true; 1.112 + } 1.113 + }, 1.114 + onProgressChange: function(a, b, c, d, e, f, g) { }, 1.115 + onSecurityChange: function(a, b, c, d) { } 1.116 + }); 1.117 + dm.addListener(getDownloadListener()); 1.118 + 1.119 + /** 1.120 + * 4. Start the download 1.121 + */ 1.122 + var destFile = dirSvc.get("ProfD", nsIF); 1.123 + destFile.append("resumed"); 1.124 + if (destFile.exists()) 1.125 + destFile.remove(false); 1.126 + var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]. 1.127 + createInstance(nsIWBP); 1.128 + persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES | 1.129 + nsIWBP.PERSIST_FLAGS_BYPASS_CACHE | 1.130 + nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; 1.131 + var dl = dm.addDownload(nsIDM.DOWNLOAD_TYPE_DOWNLOAD, 1.132 + createURI("http://localhost:" + 1.133 + httpserv.identity.primaryPort + "/resume"), 1.134 + createURI(destFile), null, null, 1.135 + Math.round(Date.now() * 1000), null, persist, false); 1.136 + persist.progressListener = dl.QueryInterface(nsIWPL); 1.137 + persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null); 1.138 + 1.139 + // Mark as pending, so clear this when we actually finish the download 1.140 + do_test_pending(); 1.141 +}