Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / netwerk / test / unit / test_backgroundfilesaver.js
blobd62cc6ddc7bcd1b65bdf4ff636b398eaed6b8b2e
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* Any copyright is dedicated to the Public Domain.
4 * http://creativecommons.org/publicdomain/zero/1.0/ */
6 /**
7 * This file tests components that implement nsIBackgroundFileSaver.
8 */
10 ////////////////////////////////////////////////////////////////////////////////
11 //// Globals
13 "use strict";
15 ChromeUtils.defineESModuleGetters(this, {
16 FileTestUtils: "resource://testing-common/FileTestUtils.sys.mjs",
17 });
19 const BackgroundFileSaverOutputStream = Components.Constructor(
20 "@mozilla.org/network/background-file-saver;1?mode=outputstream",
21 "nsIBackgroundFileSaver"
24 const BackgroundFileSaverStreamListener = Components.Constructor(
25 "@mozilla.org/network/background-file-saver;1?mode=streamlistener",
26 "nsIBackgroundFileSaver"
29 const StringInputStream = Components.Constructor(
30 "@mozilla.org/io/string-input-stream;1",
31 "nsIStringInputStream",
32 "setByteStringData"
35 const REQUEST_SUSPEND_AT = 1024 * 1024 * 4;
36 const TEST_DATA_SHORT = "This test string is written to the file.";
37 const TEST_FILE_NAME_1 = "test-backgroundfilesaver-1.txt";
38 const TEST_FILE_NAME_2 = "test-backgroundfilesaver-2.txt";
39 const TEST_FILE_NAME_3 = "test-backgroundfilesaver-3.txt";
41 // A map of test data length to the expected SHA-256 hashes
42 const EXPECTED_HASHES = {
43 // No data
44 0: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
45 // TEST_DATA_SHORT
46 40: "f37176b690e8744ee990a206c086cba54d1502aa2456c3b0c84ef6345d72a192",
47 // TEST_DATA_SHORT + TEST_DATA_SHORT
48 80: "780c0e91f50bb7ec922cc11e16859e6d5df283c0d9470f61772e3d79f41eeb58",
49 // TEST_DATA_LONG
50 4718592: "372cb9e5ce7b76d3e2a5042e78aa72dcf973e659a262c61b7ff51df74b36767b",
51 // TEST_DATA_LONG + TEST_DATA_LONG
52 9437184: "693e4f8c6855a6fed4f5f9370d12cc53105672f3ff69783581e7d925984c41d3",
55 // Generate a long string of data in a moderately fast way.
56 const TEST_256_CHARS = new Array(257).join("-");
57 const DESIRED_LENGTH = REQUEST_SUSPEND_AT * 1.125;
58 const TEST_DATA_LONG = new Array(1 + DESIRED_LENGTH / 256).join(TEST_256_CHARS);
59 Assert.equal(TEST_DATA_LONG.length, DESIRED_LENGTH);
61 /**
62 * Returns a reference to a temporary file that is guaranteed not to exist and
63 * is cleaned up later. See FileTestUtils.getTempFile for details.
65 function getTempFile(leafName) {
66 return FileTestUtils.getTempFile(leafName);
69 /**
70 * Helper function for converting a binary blob to its hex equivalent.
72 * @param str
73 * String possibly containing non-printable chars.
74 * @return A hex-encoded string.
76 function toHex(str) {
77 var hex = "";
78 for (var i = 0; i < str.length; i++) {
79 hex += ("0" + str.charCodeAt(i).toString(16)).slice(-2);
81 return hex;
84 /**
85 * Ensures that the given file contents are equal to the given string.
87 * @param aFile
88 * nsIFile whose contents should be verified.
89 * @param aExpectedContents
90 * String containing the octets that are expected in the file.
92 * @return {Promise}
93 * @resolves When the operation completes.
94 * @rejects Never.
96 function promiseVerifyContents(aFile, aExpectedContents) {
97 return new Promise(resolve => {
98 NetUtil.asyncFetch(
100 uri: NetUtil.newURI(aFile),
101 loadUsingSystemPrincipal: true,
103 function (aInputStream, aStatus) {
104 Assert.ok(Components.isSuccessCode(aStatus));
105 let contents = NetUtil.readInputStreamToString(
106 aInputStream,
107 aInputStream.available()
109 if (contents.length <= TEST_DATA_SHORT.length * 2) {
110 Assert.equal(contents, aExpectedContents);
111 } else {
112 // Do not print the entire content string to the test log.
113 Assert.equal(contents.length, aExpectedContents.length);
114 Assert.ok(contents == aExpectedContents);
116 resolve();
123 * Waits for the given saver object to complete.
125 * @param aSaver
126 * The saver, with the output stream or a stream listener implementation.
127 * @param aOnTargetChangeFn
128 * Optional callback invoked with the target file name when it changes.
130 * @return {Promise}
131 * @resolves When onSaveComplete is called with a success code.
132 * @rejects With an exception, if onSaveComplete is called with a failure code.
134 function promiseSaverComplete(aSaver, aOnTargetChangeFn) {
135 return new Promise((resolve, reject) => {
136 aSaver.observer = {
137 onTargetChange: function BFSO_onSaveComplete(saver, aTarget) {
138 if (aOnTargetChangeFn) {
139 aOnTargetChangeFn(aTarget);
142 onSaveComplete: function BFSO_onSaveComplete(saver, aStatus) {
143 if (Components.isSuccessCode(aStatus)) {
144 resolve();
145 } else {
146 reject(new Components.Exception("Saver failed.", aStatus));
154 * Feeds a string to a BackgroundFileSaverOutputStream.
156 * @param aSourceString
157 * The source data to copy.
158 * @param aSaverOutputStream
159 * The BackgroundFileSaverOutputStream to feed.
160 * @param aCloseWhenDone
161 * If true, the output stream will be closed when the copy finishes.
163 * @return {Promise}
164 * @resolves When the copy completes with a success code.
165 * @rejects With an exception, if the copy fails.
167 function promiseCopyToSaver(aSourceString, aSaverOutputStream, aCloseWhenDone) {
168 return new Promise((resolve, reject) => {
169 let inputStream = new StringInputStream(aSourceString);
170 let copier = Cc[
171 "@mozilla.org/network/async-stream-copier;1"
172 ].createInstance(Ci.nsIAsyncStreamCopier);
173 copier.init(
174 inputStream,
175 aSaverOutputStream,
176 null,
177 false,
178 true,
179 0x8000,
180 true,
181 aCloseWhenDone
183 copier.asyncCopy(
185 onStartRequest() {},
186 onStopRequest(aRequest, aStatusCode) {
187 if (Components.isSuccessCode(aStatusCode)) {
188 resolve();
189 } else {
190 reject(new Components.Exception(aStatusCode));
194 null
200 * Feeds a string to a BackgroundFileSaverStreamListener.
202 * @param aSourceString
203 * The source data to copy.
204 * @param aSaverStreamListener
205 * The BackgroundFileSaverStreamListener to feed.
206 * @param aCloseWhenDone
207 * If true, the output stream will be closed when the copy finishes.
209 * @return {Promise}
210 * @resolves When the operation completes with a success code.
211 * @rejects With an exception, if the operation fails.
213 function promisePumpToSaver(aSourceString, aSaverStreamListener) {
214 return new Promise((resolve, reject) => {
215 aSaverStreamListener.QueryInterface(Ci.nsIStreamListener);
216 let inputStream = new StringInputStream(aSourceString);
217 let pump = Cc["@mozilla.org/network/input-stream-pump;1"].createInstance(
218 Ci.nsIInputStreamPump
220 pump.init(inputStream, 0, 0, true);
221 pump.asyncRead({
222 onStartRequest: function PPTS_onStartRequest(aRequest) {
223 aSaverStreamListener.onStartRequest(aRequest);
225 onStopRequest: function PPTS_onStopRequest(aRequest, aStatusCode) {
226 aSaverStreamListener.onStopRequest(aRequest, aStatusCode);
227 if (Components.isSuccessCode(aStatusCode)) {
228 resolve();
229 } else {
230 reject(new Components.Exception(aStatusCode));
233 onDataAvailable: function PPTS_onDataAvailable(
234 aRequest,
235 aInputStream,
236 aOffset,
237 aCount
239 aSaverStreamListener.onDataAvailable(
240 aRequest,
241 aInputStream,
242 aOffset,
243 aCount
250 var gStillRunning = true;
252 ////////////////////////////////////////////////////////////////////////////////
253 //// Tests
255 add_task(function test_setup() {
256 // Wait 10 minutes, that is half of the external xpcshell timeout.
257 do_timeout(10 * 60 * 1000, function () {
258 if (gStillRunning) {
259 do_throw("Test timed out.");
264 add_task(async function test_normal() {
265 // This test demonstrates the most basic use case.
266 let destFile = getTempFile(TEST_FILE_NAME_1);
268 // Create the object implementing the output stream.
269 let saver = new BackgroundFileSaverOutputStream();
271 // Set up callbacks for completion and target file name change.
272 let receivedOnTargetChange = false;
273 function onTargetChange(aTarget) {
274 Assert.ok(destFile.equals(aTarget));
275 receivedOnTargetChange = true;
277 let completionPromise = promiseSaverComplete(saver, onTargetChange);
279 // Set the target file.
280 saver.setTarget(destFile, false);
282 // Write some data and close the output stream.
283 await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
285 // Indicate that we are ready to finish, and wait for a successful callback.
286 saver.finish(Cr.NS_OK);
287 await completionPromise;
289 // Only after we receive the completion notification, we can also be sure that
290 // we've received the target file name change notification before it.
291 Assert.ok(receivedOnTargetChange);
293 // Clean up.
294 destFile.remove(false);
297 add_task(async function test_combinations() {
298 let initialFile = getTempFile(TEST_FILE_NAME_1);
299 let renamedFile = getTempFile(TEST_FILE_NAME_2);
301 // Keep track of the current file.
302 let currentFile = null;
303 function onTargetChange(aTarget) {
304 currentFile = null;
305 info("Target file changed to: " + aTarget.leafName);
306 currentFile = aTarget;
309 // Tests various combinations of events and behaviors for both the stream
310 // listener and the output stream implementations.
311 for (let testFlags = 0; testFlags < 32; testFlags++) {
312 let keepPartialOnFailure = !!(testFlags & 1);
313 let renameAtSomePoint = !!(testFlags & 2);
314 let cancelAtSomePoint = !!(testFlags & 4);
315 let useStreamListener = !!(testFlags & 8);
316 let useLongData = !!(testFlags & 16);
318 let startTime = Date.now();
319 info(
320 "Starting keepPartialOnFailure = " +
321 keepPartialOnFailure +
322 ", renameAtSomePoint = " +
323 renameAtSomePoint +
324 ", cancelAtSomePoint = " +
325 cancelAtSomePoint +
326 ", useStreamListener = " +
327 useStreamListener +
328 ", useLongData = " +
329 useLongData
332 // Create the object and register the observers.
333 currentFile = null;
334 let saver = useStreamListener
335 ? new BackgroundFileSaverStreamListener()
336 : new BackgroundFileSaverOutputStream();
337 saver.enableSha256();
338 let completionPromise = promiseSaverComplete(saver, onTargetChange);
340 // Start feeding the first chunk of data to the saver. In case we are using
341 // the stream listener, we only write one chunk.
342 let testData = useLongData ? TEST_DATA_LONG : TEST_DATA_SHORT;
343 let feedPromise = useStreamListener
344 ? promisePumpToSaver(testData + testData, saver)
345 : promiseCopyToSaver(testData, saver, false);
347 // Set a target output file.
348 saver.setTarget(initialFile, keepPartialOnFailure);
350 // Wait for the first chunk of data to be copied.
351 await feedPromise;
353 if (renameAtSomePoint) {
354 saver.setTarget(renamedFile, keepPartialOnFailure);
357 if (cancelAtSomePoint) {
358 saver.finish(Cr.NS_ERROR_FAILURE);
361 // Feed the second chunk of data to the saver.
362 if (!useStreamListener) {
363 await promiseCopyToSaver(testData, saver, true);
366 // Wait for completion, and ensure we succeeded or failed as expected.
367 if (!cancelAtSomePoint) {
368 saver.finish(Cr.NS_OK);
370 try {
371 await completionPromise;
372 if (cancelAtSomePoint) {
373 do_throw("Failure expected.");
375 } catch (ex) {
376 if (!cancelAtSomePoint || ex.result != Cr.NS_ERROR_FAILURE) {
377 throw ex;
381 if (!cancelAtSomePoint) {
382 // In this case, the file must exist.
383 Assert.ok(currentFile.exists());
384 let expectedContents = testData + testData;
385 await promiseVerifyContents(currentFile, expectedContents);
386 Assert.equal(
387 EXPECTED_HASHES[expectedContents.length],
388 toHex(saver.sha256Hash)
390 currentFile.remove(false);
392 // If the target was really renamed, the old file should not exist.
393 if (renamedFile.equals(currentFile)) {
394 Assert.ok(!initialFile.exists());
396 } else if (!keepPartialOnFailure) {
397 // In this case, the file must not exist.
398 Assert.ok(!initialFile.exists());
399 Assert.ok(!renamedFile.exists());
400 } else {
401 // In this case, the file may or may not exist, because canceling can
402 // interrupt the asynchronous operation at any point, even before the file
403 // has been created for the first time.
404 if (initialFile.exists()) {
405 initialFile.remove(false);
407 if (renamedFile.exists()) {
408 renamedFile.remove(false);
412 info("Test case completed in " + (Date.now() - startTime) + " ms.");
416 add_task(async function test_setTarget_after_close_stream() {
417 // This test checks the case where we close the output stream before we call
418 // the setTarget method. All the data should be buffered and written anyway.
419 let destFile = getTempFile(TEST_FILE_NAME_1);
421 // Test the case where the file does not already exists first, then the case
422 // where the file already exists.
423 for (let i = 0; i < 2; i++) {
424 let saver = new BackgroundFileSaverOutputStream();
425 saver.enableSha256();
426 let completionPromise = promiseSaverComplete(saver);
428 // Copy some data to the output stream of the file saver. This data must
429 // be shorter than the internal component's pipe buffer for the test to
430 // succeed, because otherwise the test would block waiting for the write to
431 // complete.
432 await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
434 // Set the target file and wait for the output to finish.
435 saver.setTarget(destFile, false);
436 saver.finish(Cr.NS_OK);
437 await completionPromise;
439 // Verify results.
440 await promiseVerifyContents(destFile, TEST_DATA_SHORT);
441 Assert.equal(
442 EXPECTED_HASHES[TEST_DATA_SHORT.length],
443 toHex(saver.sha256Hash)
447 // Clean up.
448 destFile.remove(false);
451 add_task(async function test_setTarget_fast() {
452 // This test checks a fast rename of the target file.
453 let destFile1 = getTempFile(TEST_FILE_NAME_1);
454 let destFile2 = getTempFile(TEST_FILE_NAME_2);
455 let saver = new BackgroundFileSaverOutputStream();
456 let completionPromise = promiseSaverComplete(saver);
458 // Set the initial name after the stream is closed, then rename immediately.
459 await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
460 saver.setTarget(destFile1, false);
461 saver.setTarget(destFile2, false);
463 // Wait for all the operations to complete.
464 saver.finish(Cr.NS_OK);
465 await completionPromise;
467 // Verify results and clean up.
468 Assert.ok(!destFile1.exists());
469 await promiseVerifyContents(destFile2, TEST_DATA_SHORT);
470 destFile2.remove(false);
473 add_task(async function test_setTarget_multiple() {
474 // This test checks multiple renames of the target file.
475 let destFile = getTempFile(TEST_FILE_NAME_1);
476 let saver = new BackgroundFileSaverOutputStream();
477 let completionPromise = promiseSaverComplete(saver);
479 // Rename both before and after the stream is closed.
480 saver.setTarget(getTempFile(TEST_FILE_NAME_2), false);
481 saver.setTarget(getTempFile(TEST_FILE_NAME_3), false);
482 await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
483 saver.setTarget(getTempFile(TEST_FILE_NAME_2), false);
484 saver.setTarget(destFile, false);
486 // Wait for all the operations to complete.
487 saver.finish(Cr.NS_OK);
488 await completionPromise;
490 // Verify results and clean up.
491 Assert.ok(!getTempFile(TEST_FILE_NAME_2).exists());
492 Assert.ok(!getTempFile(TEST_FILE_NAME_3).exists());
493 await promiseVerifyContents(destFile, TEST_DATA_SHORT);
494 destFile.remove(false);
497 add_task(async function test_enableAppend() {
498 // This test checks append mode with hashing disabled.
499 let destFile = getTempFile(TEST_FILE_NAME_1);
501 // Test the case where the file does not already exists first, then the case
502 // where the file already exists.
503 for (let i = 0; i < 2; i++) {
504 let saver = new BackgroundFileSaverOutputStream();
505 saver.enableAppend();
506 let completionPromise = promiseSaverComplete(saver);
508 saver.setTarget(destFile, false);
509 await promiseCopyToSaver(TEST_DATA_LONG, saver, true);
511 saver.finish(Cr.NS_OK);
512 await completionPromise;
514 // Verify results.
515 let expectedContents =
516 i == 0 ? TEST_DATA_LONG : TEST_DATA_LONG + TEST_DATA_LONG;
517 await promiseVerifyContents(destFile, expectedContents);
520 // Clean up.
521 destFile.remove(false);
524 add_task(async function test_enableAppend_setTarget_fast() {
525 // This test checks a fast rename of the target file in append mode.
526 let destFile1 = getTempFile(TEST_FILE_NAME_1);
527 let destFile2 = getTempFile(TEST_FILE_NAME_2);
529 // Test the case where the file does not already exists first, then the case
530 // where the file already exists.
531 for (let i = 0; i < 2; i++) {
532 let saver = new BackgroundFileSaverOutputStream();
533 saver.enableAppend();
534 let completionPromise = promiseSaverComplete(saver);
536 await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
538 // The first time, we start appending to the first file and rename to the
539 // second file. The second time, we start appending to the second file,
540 // that was created the first time, and rename back to the first file.
541 let firstFile = i == 0 ? destFile1 : destFile2;
542 let secondFile = i == 0 ? destFile2 : destFile1;
543 saver.setTarget(firstFile, false);
544 saver.setTarget(secondFile, false);
546 saver.finish(Cr.NS_OK);
547 await completionPromise;
549 // Verify results.
550 Assert.ok(!firstFile.exists());
551 let expectedContents =
552 i == 0 ? TEST_DATA_SHORT : TEST_DATA_SHORT + TEST_DATA_SHORT;
553 await promiseVerifyContents(secondFile, expectedContents);
556 // Clean up.
557 destFile1.remove(false);
560 add_task(async function test_enableAppend_hash() {
561 // This test checks append mode, also verifying that the computed hash
562 // includes the contents of the existing data.
563 let destFile = getTempFile(TEST_FILE_NAME_1);
565 // Test the case where the file does not already exists first, then the case
566 // where the file already exists.
567 for (let i = 0; i < 2; i++) {
568 let saver = new BackgroundFileSaverOutputStream();
569 saver.enableAppend();
570 saver.enableSha256();
571 let completionPromise = promiseSaverComplete(saver);
573 saver.setTarget(destFile, false);
574 await promiseCopyToSaver(TEST_DATA_LONG, saver, true);
576 saver.finish(Cr.NS_OK);
577 await completionPromise;
579 // Verify results.
580 let expectedContents =
581 i == 0 ? TEST_DATA_LONG : TEST_DATA_LONG + TEST_DATA_LONG;
582 await promiseVerifyContents(destFile, expectedContents);
583 Assert.equal(
584 EXPECTED_HASHES[expectedContents.length],
585 toHex(saver.sha256Hash)
589 // Clean up.
590 destFile.remove(false);
593 add_task(async function test_finish_only() {
594 // This test checks creating the object and doing nothing.
595 let saver = new BackgroundFileSaverOutputStream();
596 function onTargetChange() {
597 do_throw("Should not receive the onTargetChange notification.");
599 let completionPromise = promiseSaverComplete(saver, onTargetChange);
600 saver.finish(Cr.NS_OK);
601 await completionPromise;
604 add_task(async function test_empty() {
605 // This test checks we still create an empty file when no data is fed.
606 let destFile = getTempFile(TEST_FILE_NAME_1);
608 let saver = new BackgroundFileSaverOutputStream();
609 let completionPromise = promiseSaverComplete(saver);
611 saver.setTarget(destFile, false);
612 await promiseCopyToSaver("", saver, true);
614 saver.finish(Cr.NS_OK);
615 await completionPromise;
617 // Verify results.
618 Assert.ok(destFile.exists());
619 Assert.equal(destFile.fileSize, 0);
621 // Clean up.
622 destFile.remove(false);
625 add_task(async function test_empty_hash() {
626 // This test checks the hash of an empty file, both in normal and append mode.
627 let destFile = getTempFile(TEST_FILE_NAME_1);
629 // Test normal mode first, then append mode.
630 for (let i = 0; i < 2; i++) {
631 let saver = new BackgroundFileSaverOutputStream();
632 if (i == 1) {
633 saver.enableAppend();
635 saver.enableSha256();
636 let completionPromise = promiseSaverComplete(saver);
638 saver.setTarget(destFile, false);
639 await promiseCopyToSaver("", saver, true);
641 saver.finish(Cr.NS_OK);
642 await completionPromise;
644 // Verify results.
645 Assert.equal(destFile.fileSize, 0);
646 Assert.equal(EXPECTED_HASHES[0], toHex(saver.sha256Hash));
649 // Clean up.
650 destFile.remove(false);
653 add_task(async function test_invalid_hash() {
654 let saver = new BackgroundFileSaverStreamListener();
655 let completionPromise = promiseSaverComplete(saver);
656 // We shouldn't be able to get the hash if hashing hasn't been enabled
657 try {
658 saver.sha256Hash;
659 do_throw("Shouldn't be able to get hash if hashing not enabled");
660 } catch (ex) {
661 if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
662 throw ex;
665 // Enable hashing, but don't feed any data to saver
666 saver.enableSha256();
667 let destFile = getTempFile(TEST_FILE_NAME_1);
668 saver.setTarget(destFile, false);
669 // We don't wait on promiseSaverComplete, so the hash getter can run before
670 // or after onSaveComplete is called. However, the expected behavior is the
671 // same in both cases since the hash is only valid when the save completes
672 // successfully.
673 saver.finish(Cr.NS_ERROR_FAILURE);
674 try {
675 saver.sha256Hash;
676 do_throw("Shouldn't be able to get hash if save did not succeed");
677 } catch (ex) {
678 if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
679 throw ex;
682 // Wait for completion so that the worker thread finishes dealing with the
683 // target file. We expect it to fail.
684 try {
685 await completionPromise;
686 do_throw("completionPromise should throw");
687 } catch (ex) {
688 if (ex.result != Cr.NS_ERROR_FAILURE) {
689 throw ex;
694 add_task(async function test_signature() {
695 // Check that we get a signature if the saver is finished.
696 let destFile = getTempFile(TEST_FILE_NAME_1);
698 let saver = new BackgroundFileSaverOutputStream();
699 let completionPromise = promiseSaverComplete(saver);
701 try {
702 saver.signatureInfo;
703 do_throw("Can't get signature if saver is not complete");
704 } catch (ex) {
705 if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
706 throw ex;
710 saver.enableSignatureInfo();
711 saver.setTarget(destFile, false);
712 await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
714 saver.finish(Cr.NS_OK);
715 await completionPromise;
716 await promiseVerifyContents(destFile, TEST_DATA_SHORT);
718 // signatureInfo is an empty nsIArray
719 Assert.equal(0, saver.signatureInfo.length);
721 // Clean up.
722 destFile.remove(false);
725 add_task(async function test_signature_not_enabled() {
726 // Check that we get a signature if the saver is finished on Windows.
727 let destFile = getTempFile(TEST_FILE_NAME_1);
729 let saver = new BackgroundFileSaverOutputStream();
730 let completionPromise = promiseSaverComplete(saver);
731 saver.setTarget(destFile, false);
732 await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
734 saver.finish(Cr.NS_OK);
735 await completionPromise;
736 try {
737 saver.signatureInfo;
738 do_throw("Can't get signature if not enabled");
739 } catch (ex) {
740 if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
741 throw ex;
745 // Clean up.
746 destFile.remove(false);
749 add_task(function test_teardown() {
750 gStillRunning = false;