|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 "use strict"; |
|
5 |
|
6 Components.utils.import("resource://gre/modules/ctypes.jsm"); |
|
7 Components.utils.import("resource://gre/modules/osfile.jsm"); |
|
8 Components.utils.import("resource://gre/modules/Task.jsm"); |
|
9 |
|
10 /** |
|
11 * A test to check that .getPosition/.setPosition work with large files. |
|
12 * (see bug 952997) |
|
13 */ |
|
14 |
|
15 // Test setPosition/getPosition. |
|
16 function test_setPosition(forward, current, backward) { |
|
17 let path = OS.Path.join(OS.Constants.Path.tmpDir, |
|
18 "test_osfile_async_largefiles.tmp"); |
|
19 |
|
20 // Clear any left-over files from previous runs. |
|
21 try { |
|
22 yield OS.File.remove(path); |
|
23 } catch (ex if ex.becauseNoSuchFile) { |
|
24 // ignore |
|
25 } |
|
26 |
|
27 try { |
|
28 let file = yield OS.File.open(path, {write:true, append:false}); |
|
29 try { |
|
30 let pos = 0; |
|
31 |
|
32 // 1. seek forward from start |
|
33 do_print("Moving forward: " + forward); |
|
34 yield file.setPosition(forward, OS.File.POS_START); |
|
35 pos += forward; |
|
36 do_check_eq((yield file.getPosition()), pos); |
|
37 |
|
38 // 2. seek forward from current position |
|
39 do_print("Moving current: " + current); |
|
40 yield file.setPosition(current, OS.File.POS_CURRENT); |
|
41 pos += current; |
|
42 do_check_eq((yield file.getPosition()), pos); |
|
43 |
|
44 // 3. seek backward from current position |
|
45 do_print("Moving current backward: " + backward); |
|
46 yield file.setPosition(-backward, OS.File.POS_CURRENT); |
|
47 pos -= backward; |
|
48 do_check_eq((yield file.getPosition()), pos); |
|
49 |
|
50 } finally { |
|
51 yield file.setPosition(0, OS.File.POS_START); |
|
52 yield file.close(); |
|
53 } |
|
54 } catch(ex) { |
|
55 try { |
|
56 yield OS.File.remove(path); |
|
57 } catch (ex if ex.becauseNoSuchFile) { |
|
58 // ignore. |
|
59 } |
|
60 do_throw(ex); |
|
61 } |
|
62 } |
|
63 |
|
64 // Test setPosition/getPosition expected failures. |
|
65 function test_setPosition_failures() { |
|
66 let path = OS.Path.join(OS.Constants.Path.tmpDir, |
|
67 "test_osfile_async_largefiles.tmp"); |
|
68 |
|
69 // Clear any left-over files from previous runs. |
|
70 try { |
|
71 yield OS.File.remove(path); |
|
72 } catch (ex if ex.becauseNoSuchFile) { |
|
73 // ignore |
|
74 } |
|
75 |
|
76 try { |
|
77 let file = yield OS.File.open(path, {write:true, append:false}); |
|
78 try { |
|
79 let pos = 0; |
|
80 |
|
81 // 1. Use an invalid position value |
|
82 try { |
|
83 yield file.setPosition(0.5, OS.File.POS_START); |
|
84 do_throw("Shouldn't have succeeded"); |
|
85 } catch (ex) { |
|
86 do_check_true(ex.toString().contains("expected type")); |
|
87 } |
|
88 // Since setPosition should have bailed, it shouldn't have moved the |
|
89 // file pointer at all. |
|
90 do_check_eq((yield file.getPosition()), 0); |
|
91 |
|
92 // 2. Use an invalid position value |
|
93 try { |
|
94 yield file.setPosition(0xffffffff + 0.5, OS.File.POS_START); |
|
95 do_throw("Shouldn't have succeeded"); |
|
96 } catch (ex) { |
|
97 do_check_true(ex.toString().contains("expected type")); |
|
98 } |
|
99 // Since setPosition should have bailed, it shouldn't have moved the |
|
100 // file pointer at all. |
|
101 do_check_eq((yield file.getPosition()), 0); |
|
102 |
|
103 // 3. Use a position that cannot be represented as a double |
|
104 try { |
|
105 // Not all numbers after 9007199254740992 can be represented as a |
|
106 // double. E.g. in js 9007199254740992 + 1 == 9007199254740992 |
|
107 yield file.setPosition(9007199254740992, OS.File.POS_START); |
|
108 yield file.setPosition(1, OS.File.POS_CURRENT); |
|
109 do_throw("Shouldn't have succeeded"); |
|
110 } catch (ex) { |
|
111 do_print(ex.toString()); |
|
112 do_check_true(!!ex); |
|
113 } |
|
114 |
|
115 } finally { |
|
116 yield file.setPosition(0, OS.File.POS_START); |
|
117 yield file.close(); |
|
118 try { |
|
119 yield OS.File.remove(path); |
|
120 } catch (ex if ex.becauseNoSuchFile) { |
|
121 // ignore. |
|
122 } |
|
123 } |
|
124 } catch(ex) { |
|
125 do_throw(ex); |
|
126 } |
|
127 } |
|
128 |
|
129 function run_test() { |
|
130 // First verify stuff works for small values. |
|
131 add_task(test_setPosition.bind(null, 0, 100, 50)); |
|
132 add_task(test_setPosition.bind(null, 1000, 100, 50)); |
|
133 add_task(test_setPosition.bind(null, 1000, -100, -50)); |
|
134 |
|
135 if (OS.Constants.Win || ctypes.off_t.size >= 8) { |
|
136 // Now verify stuff still works for large values. |
|
137 // 1. Multiple small seeks, which add up to > MAXINT32 |
|
138 add_task(test_setPosition.bind(null, 0x7fffffff, 0x7fffffff, 0)); |
|
139 // 2. Plain large seek, that should end up at 0 again. |
|
140 // 0xffffffff also happens to be the INVALID_SET_FILE_POINTER value on |
|
141 // Windows, so this also tests the error handling |
|
142 add_task(test_setPosition.bind(null, 0, 0xffffffff, 0xffffffff)); |
|
143 // 3. Multiple large seeks that should end up > MAXINT32. |
|
144 add_task(test_setPosition.bind(null, 0xffffffff, 0xffffffff, 0xffffffff)); |
|
145 // 5. Multiple large seeks with negative offsets. |
|
146 add_task(test_setPosition.bind(null, 0xffffffff, -0x7fffffff, 0x7fffffff)); |
|
147 |
|
148 // 6. Check failures |
|
149 add_task(test_setPosition_failures); |
|
150 } |
|
151 |
|
152 run_next_test(); |
|
153 } |