diff options
Diffstat (limited to 'toolkit/components/downloads/test/unit/test_DownloadCore.js')
-rw-r--r-- | toolkit/components/downloads/test/unit/test_DownloadCore.js | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/toolkit/components/downloads/test/unit/test_DownloadCore.js b/toolkit/components/downloads/test/unit/test_DownloadCore.js new file mode 100644 index 0000000000..41aeaac33b --- /dev/null +++ b/toolkit/components/downloads/test/unit/test_DownloadCore.js @@ -0,0 +1,291 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests the main download interfaces using DownloadCopySaver. + */ + +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + DownloadError: "resource://gre/modules/DownloadCore.sys.mjs", +}); + +// Execution of common tests + +// This is used in common_test_Download.js +// eslint-disable-next-line no-unused-vars +var gUseLegacySaver = false; + +var scriptFile = do_get_file("common_test_Download.js"); +Services.scriptloader.loadSubScript(NetUtil.newURI(scriptFile).spec); + +// Tests + +/** + * The download should fail early if the source and the target are the same. + */ +add_task(async function test_error_target_downloadingToSameFile() { + let targetFile = getTempFile(TEST_TARGET_FILE_NAME); + targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + + let download = await Downloads.createDownload({ + source: NetUtil.newURI(targetFile), + target: targetFile, + }); + await Assert.rejects( + download.start(), + ex => ex instanceof Downloads.Error && ex.becauseTargetFailed + ); + + Assert.ok( + await IOUtils.exists(download.target.path), + "The file should not have been deleted." + ); +}); + +/** + * Tests allowHttpStatus allowing requests + */ +add_task(async function test_error_notfound() { + const targetFile = getTempFile(TEST_TARGET_FILE_NAME); + let called = false; + const download = await Downloads.createDownload({ + source: { + url: httpUrl("notfound.gone"), + allowHttpStatus(aDownload, aStatusCode) { + Assert.strictEqual(download, aDownload, "Check Download objects"); + Assert.strictEqual(aStatusCode, 404, "The status should be correct"); + called = true; + return true; + }, + }, + target: targetFile, + }); + await download.start(); + Assert.ok(called, "allowHttpStatus should have been called"); +}); + +/** + * Tests allowHttpStatus rejecting requests + */ +add_task(async function test_error_notfound_reject() { + const targetFile = getTempFile(TEST_TARGET_FILE_NAME); + let called = false; + const download = await Downloads.createDownload({ + source: { + url: httpUrl("notfound.gone"), + allowHttpStatus(aDownload, aStatusCode) { + Assert.strictEqual(download, aDownload, "Check Download objects"); + Assert.strictEqual(aStatusCode, 404, "The status should be correct"); + called = true; + return false; + }, + }, + target: targetFile, + }); + await Assert.rejects( + download.start(), + ex => ex instanceof Downloads.Error && ex.becauseSourceFailed, + "Download should have been rejected" + ); + Assert.ok(called, "allowHttpStatus should have been called"); +}); + +/** + * Tests allowHttpStatus rejecting requests other than 404 + */ +add_task(async function test_error_busy_reject() { + const targetFile = getTempFile(TEST_TARGET_FILE_NAME); + let called = false; + const download = await Downloads.createDownload({ + source: { + url: httpUrl("busy.txt"), + allowHttpStatus(aDownload, aStatusCode) { + Assert.strictEqual(download, aDownload, "Check Download objects"); + Assert.strictEqual(aStatusCode, 504, "The status should be correct"); + called = true; + return false; + }, + }, + target: targetFile, + }); + await Assert.rejects( + download.start(), + ex => ex instanceof Downloads.Error && ex.becauseSourceFailed, + "Download should have been rejected" + ); + Assert.ok(called, "allowHttpStatus should have been called"); +}); + +/** + * Tests redirects are followed correctly, and the meta data corresponds + * to the correct, final response + */ +add_task(async function test_redirects() { + const targetFile = getTempFile(TEST_TARGET_FILE_NAME); + let called = false; + const download = await Downloads.createDownload({ + source: { + url: httpUrl("redirect"), + allowHttpStatus(aDownload, aStatusCode) { + Assert.strictEqual(download, aDownload, "Check Download objects"); + Assert.strictEqual( + aStatusCode, + 504, + "The status should be correct after a redirect" + ); + called = true; + return true; + }, + }, + target: targetFile, + }); + await download.start(); + Assert.equal( + download.contentType, + "text/plain", + "Content-Type is correct after redirect" + ); + Assert.equal( + download.totalBytes, + TEST_DATA_SHORT.length, + "Content-Length is correct after redirect" + ); + Assert.equal(download.target.size, TEST_DATA_SHORT.length); + Assert.ok(called, "allowHttpStatus should have been called"); +}); + +/** + * Tests the DownloadError object. + */ +add_task(function test_DownloadError() { + let error = new DownloadError({ + result: Cr.NS_ERROR_NOT_RESUMABLE, + message: "Not resumable.", + }); + Assert.equal(error.result, Cr.NS_ERROR_NOT_RESUMABLE); + Assert.equal(error.message, "Not resumable."); + Assert.ok(!error.becauseSourceFailed); + Assert.ok(!error.becauseTargetFailed); + Assert.ok(!error.becauseBlocked); + Assert.ok(!error.becauseBlockedByParentalControls); + + error = new DownloadError({ message: "Unknown error." }); + Assert.equal(error.result, Cr.NS_ERROR_FAILURE); + Assert.equal(error.message, "Unknown error."); + + error = new DownloadError({ result: Cr.NS_ERROR_NOT_RESUMABLE }); + Assert.equal(error.result, Cr.NS_ERROR_NOT_RESUMABLE); + Assert.ok(error.message.indexOf("Exception") > 0); + + // becauseSourceFailed will be set, but not the unknown property. + error = new DownloadError({ + message: "Unknown error.", + becauseSourceFailed: true, + becauseUnknown: true, + }); + Assert.ok(error.becauseSourceFailed); + Assert.equal(false, "becauseUnknown" in error); + + error = new DownloadError({ + result: Cr.NS_ERROR_MALFORMED_URI, + inferCause: true, + }); + Assert.equal(error.result, Cr.NS_ERROR_MALFORMED_URI); + Assert.ok(error.becauseSourceFailed); + Assert.ok(!error.becauseTargetFailed); + Assert.ok(!error.becauseBlocked); + Assert.ok(!error.becauseBlockedByParentalControls); + + // This test does not set inferCause, so becauseSourceFailed will not be set. + error = new DownloadError({ result: Cr.NS_ERROR_MALFORMED_URI }); + Assert.equal(error.result, Cr.NS_ERROR_MALFORMED_URI); + Assert.ok(!error.becauseSourceFailed); + + error = new DownloadError({ + result: Cr.NS_ERROR_FILE_INVALID_PATH, + inferCause: true, + }); + Assert.equal(error.result, Cr.NS_ERROR_FILE_INVALID_PATH); + Assert.ok(!error.becauseSourceFailed); + Assert.ok(error.becauseTargetFailed); + Assert.ok(!error.becauseBlocked); + Assert.ok(!error.becauseBlockedByParentalControls); + + error = new DownloadError({ becauseBlocked: true }); + Assert.equal(error.message, "Download blocked."); + Assert.ok(!error.becauseSourceFailed); + Assert.ok(!error.becauseTargetFailed); + Assert.ok(error.becauseBlocked); + Assert.ok(!error.becauseBlockedByParentalControls); + + error = new DownloadError({ becauseBlockedByParentalControls: true }); + Assert.equal(error.message, "Download blocked."); + Assert.ok(!error.becauseSourceFailed); + Assert.ok(!error.becauseTargetFailed); + Assert.ok(error.becauseBlocked); + Assert.ok(error.becauseBlockedByParentalControls); +}); + +add_task(async function test_cancel_interrupted_download() { + let targetFile = getTempFile(TEST_TARGET_FILE_NAME); + + let download = await Downloads.createDownload({ + source: httpUrl("interruptible_resumable.txt"), + target: targetFile, + }); + + async function createAndCancelDownload() { + info("Create an interruptible download and cancel it midway"); + mustInterruptResponses(); + const promiseDownloaded = download.start(); + await promiseDownloadMidway(download); + await download.cancel(); + + info("Unblock the interruptible download and wait for its annotation"); + continueResponses(); + await waitForAnnotation( + httpUrl("interruptible_resumable.txt"), + "downloads/destinationFileURI" + ); + + await Assert.rejects( + promiseDownloaded, + /DownloadError: Download canceled/, + "Got a download error as expected" + ); + } + + await new Promise(resolve => { + const DONE = "=== download xpcshell test console listener done ==="; + const logDone = () => Services.console.logStringMessage(DONE); + const consoleListener = msg => { + if (msg == DONE) { + Services.console.unregisterListener(consoleListener); + resolve(); + } + }; + Services.console.reset(); + Services.console.registerListener(consoleListener); + + createAndCancelDownload().then(logDone); + }); + + info( + "Assert that nsIStreamListener.onDataAvailable has not been called after download.cancel" + ); + let found = Services.console + .getMessageArray() + .map(m => m.message) + .filter(message => { + return message.includes("nsIStreamListener.onDataAvailable"); + }); + Assert.deepEqual( + found, + [], + "Expect no nsIStreamListener.onDataAvaialable error" + ); +}); |