Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 let Cc = Components.classes;
5 let Ci = Components.interfaces;
7 // We need the profile directory so the test harness will clean up our test
8 // files.
9 do_get_profile();
11 const OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/file-output-stream;1";
12 const SAFE_OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/safe-file-output-stream;1";
14 ////////////////////////////////////////////////////////////////////////////////
15 //// Helper Methods
17 /**
18 * Generates a leafName for a file that does not exist, but does *not*
19 * create the file. Similar to createUnique except for the fact that createUnique
20 * does create the file.
21 *
22 * @param aFile
23 * The file to modify in order for it to have a unique leafname.
24 */
25 function ensure_unique(aFile)
26 {
27 ensure_unique.fileIndex = ensure_unique.fileIndex || 0;
29 var leafName = aFile.leafName;
30 while (aFile.clone().exists()) {
31 aFile.leafName = leafName + "_" + (ensure_unique.fileIndex++);
32 }
33 }
35 /**
36 * Tests for files being accessed at the right time. Streams that use
37 * DEFER_OPEN should only open or create the file when an operation is
38 * done, and not during Init().
39 *
40 * Note that for writing, we check for actual writing in test_NetUtil (async)
41 * and in sync_operations in this file (sync), whereas in this function we
42 * just check that the file is *not* created during init.
43 *
44 * @param aContractId
45 * The contract ID to use for the output stream
46 * @param aDeferOpen
47 * Whether to check with DEFER_OPEN or not
48 * @param aTrickDeferredOpen
49 * Whether we try to 'trick' deferred opens by changing the file object before
50 * the actual open. The stream should have a clone, so changes to the file
51 * object after Init and before Open should not affect it.
52 */
53 function check_access(aContractId, aDeferOpen, aTrickDeferredOpen)
54 {
55 const LEAF_NAME = "filestreams-test-file.tmp";
56 const TRICKY_LEAF_NAME = "BetYouDidNotExpectThat.tmp";
57 let file = Cc["@mozilla.org/file/directory_service;1"].
58 getService(Ci.nsIProperties).
59 get("ProfD", Ci.nsIFile);
60 file.append(LEAF_NAME);
62 // Writing
64 ensure_unique(file);
65 let ostream = Cc[aContractId].createInstance(Ci.nsIFileOutputStream);
66 ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0);
67 do_check_eq(aDeferOpen, !file.clone().exists()); // If defer, should not exist and vice versa
68 if (aDeferOpen) {
69 // File should appear when we do write to it.
70 if (aTrickDeferredOpen) {
71 // See |@param aDeferOpen| in the JavaDoc comment for this function
72 file.leafName = TRICKY_LEAF_NAME;
73 }
74 ostream.write("data", 4);
75 if (aTrickDeferredOpen) {
76 file.leafName = LEAF_NAME;
77 }
78 // We did a write, so the file should now exist
79 do_check_true(file.clone().exists());
80 }
81 ostream.close();
83 // Reading
85 ensure_unique(file);
86 let istream = Cc["@mozilla.org/network/file-input-stream;1"].
87 createInstance(Ci.nsIFileInputStream);
88 var initOk, getOk;
89 try {
90 istream.init(file, -1, 0, aDeferOpen ? Ci.nsIFileInputStream.DEFER_OPEN : 0);
91 initOk = true;
92 }
93 catch(e) {
94 initOk = false;
95 }
96 try {
97 let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
98 createInstance(Ci.nsIFileInputStream);
99 fstream.init(aFile, -1, 0, 0);
100 getOk = true;
101 }
102 catch(e) {
103 getOk = false;
104 }
106 // If the open is deferred, then Init should succeed even though the file we
107 // intend to read does not exist, and then trying to read from it should
108 // fail. The other case is where the open is not deferred, and there we should
109 // get an error when we Init (and also when we try to read).
110 do_check_true( (aDeferOpen && initOk && !getOk) ||
111 (!aDeferOpen && !initOk && !getOk) );
112 istream.close();
113 }
115 /**
116 * We test async operations in test_NetUtil.js, and here test for simple sync
117 * operations on input streams.
118 *
119 * @param aDeferOpen
120 * Whether to use DEFER_OPEN in the streams.
121 */
122 function sync_operations(aDeferOpen)
123 {
124 const TEST_DATA = "this is a test string";
125 const LEAF_NAME = "filestreams-test-file.tmp";
127 let file = Cc["@mozilla.org/file/directory_service;1"].
128 getService(Ci.nsIProperties).
129 get("ProfD", Ci.nsIFile);
130 file.append(LEAF_NAME);
131 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
133 let ostream = Cc[OUTPUT_STREAM_CONTRACT_ID].
134 createInstance(Ci.nsIFileOutputStream);
135 ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0);
137 ostream.write(TEST_DATA, TEST_DATA.length);
138 ostream.close();
140 let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
141 createInstance(Ci.nsIFileInputStream);
142 fstream.init(file, -1, 0, aDeferOpen ? Ci.nsIFileInputStream.DEFER_OPEN : 0);
144 let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
145 createInstance(Ci.nsIConverterInputStream);
146 cstream.init(fstream, "UTF-8", 0, 0);
148 let string = {};
149 cstream.readString(-1, string);
150 cstream.close();
151 fstream.close();
153 do_check_eq(string.value, TEST_DATA);
154 }
156 ////////////////////////////////////////////////////////////////////////////////
157 //// Tests
159 function test_access()
160 {
161 check_access(OUTPUT_STREAM_CONTRACT_ID, false, false);
162 }
164 function test_access_trick()
165 {
166 check_access(OUTPUT_STREAM_CONTRACT_ID, false, true);
167 }
169 function test_access_defer()
170 {
171 check_access(OUTPUT_STREAM_CONTRACT_ID, true, false);
172 }
174 function test_access_defer_trick()
175 {
176 check_access(OUTPUT_STREAM_CONTRACT_ID, true, true);
177 }
179 function test_access_safe()
180 {
181 check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, false, false);
182 }
184 function test_access_safe_trick()
185 {
186 check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, false, true);
187 }
189 function test_access_safe_defer()
190 {
191 check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, true, false);
192 }
194 function test_access_safe_defer_trick()
195 {
196 check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, true, true);
197 }
199 function test_sync_operations()
200 {
201 sync_operations();
202 }
204 function test_sync_operations_deferred()
205 {
206 sync_operations(true);
207 }
209 function do_test_zero_size_buffered(disableBuffering)
210 {
211 const LEAF_NAME = "filestreams-test-file.tmp";
212 const BUFFERSIZE = 4096;
214 let file = Cc["@mozilla.org/file/directory_service;1"].
215 getService(Ci.nsIProperties).
216 get("ProfD", Ci.nsIFile);
217 file.append(LEAF_NAME);
218 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
220 let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
221 createInstance(Ci.nsIFileInputStream);
222 fstream.init(file, -1, 0,
223 Ci.nsIFileInputStream.CLOSE_ON_EOF |
224 Ci.nsIFileInputStream.REOPEN_ON_REWIND);
226 var buffered = Cc["@mozilla.org/network/buffered-input-stream;1"].
227 createInstance(Ci.nsIBufferedInputStream);
228 buffered.init(fstream, BUFFERSIZE);
230 if (disableBuffering) {
231 buffered.QueryInterface(Ci.nsIStreamBufferAccess).disableBuffering();
232 }
234 // Scriptable input streams clamp read sizes to the return value of
235 // available(), so don't quite do what we want here.
236 let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
237 createInstance(Ci.nsIConverterInputStream);
238 cstream.init(buffered, "UTF-8", 0, 0);
240 do_check_eq(buffered.available(), 0);
242 // Now try reading from this stream
243 let string = {};
244 do_check_eq(cstream.readString(BUFFERSIZE, string), 0);
245 do_check_eq(string.value, "");
247 // Now check that available() throws
248 var exceptionThrown = false;
249 try {
250 do_check_eq(buffered.available(), 0);
251 } catch (e) {
252 exceptionThrown = true;
253 }
254 do_check_true(exceptionThrown);
256 // OK, now seek back to start
257 buffered.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
259 // Now check that available() does not throw
260 exceptionThrown = false;
261 try {
262 do_check_eq(buffered.available(), 0);
263 } catch (e) {
264 exceptionThrown = true;
265 }
266 do_check_false(exceptionThrown);
267 }
269 function test_zero_size_buffered()
270 {
271 do_test_zero_size_buffered(false);
272 do_test_zero_size_buffered(true);
273 }
275 ////////////////////////////////////////////////////////////////////////////////
276 //// Test Runner
278 let tests = [
279 test_access,
280 test_access_trick,
281 test_access_defer,
282 test_access_defer_trick,
283 test_access_safe,
284 test_access_safe_trick,
285 test_access_safe_defer,
286 test_access_safe_defer_trick,
287 test_sync_operations,
288 test_sync_operations_deferred,
289 test_zero_size_buffered,
290 ];
292 function run_test()
293 {
294 tests.forEach(function(test) {
295 test();
296 });
297 }