summaryrefslogtreecommitdiffstats
path: root/toolkit/components/osfile/tests/xpcshell/test_osfile_async_largefiles.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/osfile/tests/xpcshell/test_osfile_async_largefiles.js')
-rw-r--r--toolkit/components/osfile/tests/xpcshell/test_osfile_async_largefiles.js153
1 files changed, 153 insertions, 0 deletions
diff --git a/toolkit/components/osfile/tests/xpcshell/test_osfile_async_largefiles.js b/toolkit/components/osfile/tests/xpcshell/test_osfile_async_largefiles.js
new file mode 100644
index 000000000..a9ac776b0
--- /dev/null
+++ b/toolkit/components/osfile/tests/xpcshell/test_osfile_async_largefiles.js
@@ -0,0 +1,153 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+Components.utils.import("resource://gre/modules/ctypes.jsm");
+Components.utils.import("resource://gre/modules/osfile.jsm");
+Components.utils.import("resource://gre/modules/Task.jsm");
+
+/**
+ * A test to check that .getPosition/.setPosition work with large files.
+ * (see bug 952997)
+ */
+
+// Test setPosition/getPosition.
+function test_setPosition(forward, current, backward) {
+ let path = OS.Path.join(OS.Constants.Path.tmpDir,
+ "test_osfile_async_largefiles.tmp");
+
+ // Clear any left-over files from previous runs.
+ try {
+ yield OS.File.remove(path);
+ } catch (ex if ex.becauseNoSuchFile) {
+ // ignore
+ }
+
+ try {
+ let file = yield OS.File.open(path, {write:true, append:false});
+ try {
+ let pos = 0;
+
+ // 1. seek forward from start
+ do_print("Moving forward: " + forward);
+ yield file.setPosition(forward, OS.File.POS_START);
+ pos += forward;
+ do_check_eq((yield file.getPosition()), pos);
+
+ // 2. seek forward from current position
+ do_print("Moving current: " + current);
+ yield file.setPosition(current, OS.File.POS_CURRENT);
+ pos += current;
+ do_check_eq((yield file.getPosition()), pos);
+
+ // 3. seek backward from current position
+ do_print("Moving current backward: " + backward);
+ yield file.setPosition(-backward, OS.File.POS_CURRENT);
+ pos -= backward;
+ do_check_eq((yield file.getPosition()), pos);
+
+ } finally {
+ yield file.setPosition(0, OS.File.POS_START);
+ yield file.close();
+ }
+ } catch(ex) {
+ try {
+ yield OS.File.remove(path);
+ } catch (ex if ex.becauseNoSuchFile) {
+ // ignore.
+ }
+ do_throw(ex);
+ }
+}
+
+// Test setPosition/getPosition expected failures.
+function test_setPosition_failures() {
+ let path = OS.Path.join(OS.Constants.Path.tmpDir,
+ "test_osfile_async_largefiles.tmp");
+
+ // Clear any left-over files from previous runs.
+ try {
+ yield OS.File.remove(path);
+ } catch (ex if ex.becauseNoSuchFile) {
+ // ignore
+ }
+
+ try {
+ let file = yield OS.File.open(path, {write:true, append:false});
+ try {
+ let pos = 0;
+
+ // 1. Use an invalid position value
+ try {
+ yield file.setPosition(0.5, OS.File.POS_START);
+ do_throw("Shouldn't have succeeded");
+ } catch (ex) {
+ do_check_true(ex.toString().includes("can't pass"));
+ }
+ // Since setPosition should have bailed, it shouldn't have moved the
+ // file pointer at all.
+ do_check_eq((yield file.getPosition()), 0);
+
+ // 2. Use an invalid position value
+ try {
+ yield file.setPosition(0xffffffff + 0.5, OS.File.POS_START);
+ do_throw("Shouldn't have succeeded");
+ } catch (ex) {
+ do_check_true(ex.toString().includes("can't pass"));
+ }
+ // Since setPosition should have bailed, it shouldn't have moved the
+ // file pointer at all.
+ do_check_eq((yield file.getPosition()), 0);
+
+ // 3. Use a position that cannot be represented as a double
+ try {
+ // Not all numbers after 9007199254740992 can be represented as a
+ // double. E.g. in js 9007199254740992 + 1 == 9007199254740992
+ yield file.setPosition(9007199254740992, OS.File.POS_START);
+ yield file.setPosition(1, OS.File.POS_CURRENT);
+ do_throw("Shouldn't have succeeded");
+ } catch (ex) {
+ do_print(ex.toString());
+ do_check_true(!!ex);
+ }
+
+ } finally {
+ yield file.setPosition(0, OS.File.POS_START);
+ yield file.close();
+ try {
+ yield OS.File.remove(path);
+ } catch (ex if ex.becauseNoSuchFile) {
+ // ignore.
+ }
+ }
+ } catch(ex) {
+ do_throw(ex);
+ }
+}
+
+function run_test() {
+ // First verify stuff works for small values.
+ add_task(test_setPosition.bind(null, 0, 100, 50));
+ add_task(test_setPosition.bind(null, 1000, 100, 50));
+ add_task(test_setPosition.bind(null, 1000, -100, -50));
+
+ if (OS.Constants.Win || ctypes.off_t.size >= 8) {
+ // Now verify stuff still works for large values.
+ // 1. Multiple small seeks, which add up to > MAXINT32
+ add_task(test_setPosition.bind(null, 0x7fffffff, 0x7fffffff, 0));
+ // 2. Plain large seek, that should end up at 0 again.
+ // 0xffffffff also happens to be the INVALID_SET_FILE_POINTER value on
+ // Windows, so this also tests the error handling
+ add_task(test_setPosition.bind(null, 0, 0xffffffff, 0xffffffff));
+ // 3. Multiple large seeks that should end up > MAXINT32.
+ add_task(test_setPosition.bind(null, 0xffffffff, 0xffffffff, 0xffffffff));
+ // 5. Multiple large seeks with negative offsets.
+ add_task(test_setPosition.bind(null, 0xffffffff, -0x7fffffff, 0x7fffffff));
+
+ // 6. Check failures
+ add_task(test_setPosition_failures);
+ }
+
+ run_next_test();
+}