summaryrefslogtreecommitdiffstats
path: root/toolkit/components/osfile/tests/xpcshell/test_osfile_async_largefiles.js
blob: a9ac776b0bb0167a8bc55a6bb195bd1563ae983e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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();
}