1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/test/unit/test_filestreams.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,298 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +let Cc = Components.classes; 1.8 +let Ci = Components.interfaces; 1.9 + 1.10 +// We need the profile directory so the test harness will clean up our test 1.11 +// files. 1.12 +do_get_profile(); 1.13 + 1.14 +const OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/file-output-stream;1"; 1.15 +const SAFE_OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/safe-file-output-stream;1"; 1.16 + 1.17 +//////////////////////////////////////////////////////////////////////////////// 1.18 +//// Helper Methods 1.19 + 1.20 +/** 1.21 + * Generates a leafName for a file that does not exist, but does *not* 1.22 + * create the file. Similar to createUnique except for the fact that createUnique 1.23 + * does create the file. 1.24 + * 1.25 + * @param aFile 1.26 + * The file to modify in order for it to have a unique leafname. 1.27 + */ 1.28 +function ensure_unique(aFile) 1.29 +{ 1.30 + ensure_unique.fileIndex = ensure_unique.fileIndex || 0; 1.31 + 1.32 + var leafName = aFile.leafName; 1.33 + while (aFile.clone().exists()) { 1.34 + aFile.leafName = leafName + "_" + (ensure_unique.fileIndex++); 1.35 + } 1.36 +} 1.37 + 1.38 +/** 1.39 + * Tests for files being accessed at the right time. Streams that use 1.40 + * DEFER_OPEN should only open or create the file when an operation is 1.41 + * done, and not during Init(). 1.42 + * 1.43 + * Note that for writing, we check for actual writing in test_NetUtil (async) 1.44 + * and in sync_operations in this file (sync), whereas in this function we 1.45 + * just check that the file is *not* created during init. 1.46 + * 1.47 + * @param aContractId 1.48 + * The contract ID to use for the output stream 1.49 + * @param aDeferOpen 1.50 + * Whether to check with DEFER_OPEN or not 1.51 + * @param aTrickDeferredOpen 1.52 + * Whether we try to 'trick' deferred opens by changing the file object before 1.53 + * the actual open. The stream should have a clone, so changes to the file 1.54 + * object after Init and before Open should not affect it. 1.55 + */ 1.56 +function check_access(aContractId, aDeferOpen, aTrickDeferredOpen) 1.57 +{ 1.58 + const LEAF_NAME = "filestreams-test-file.tmp"; 1.59 + const TRICKY_LEAF_NAME = "BetYouDidNotExpectThat.tmp"; 1.60 + let file = Cc["@mozilla.org/file/directory_service;1"]. 1.61 + getService(Ci.nsIProperties). 1.62 + get("ProfD", Ci.nsIFile); 1.63 + file.append(LEAF_NAME); 1.64 + 1.65 + // Writing 1.66 + 1.67 + ensure_unique(file); 1.68 + let ostream = Cc[aContractId].createInstance(Ci.nsIFileOutputStream); 1.69 + ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0); 1.70 + do_check_eq(aDeferOpen, !file.clone().exists()); // If defer, should not exist and vice versa 1.71 + if (aDeferOpen) { 1.72 + // File should appear when we do write to it. 1.73 + if (aTrickDeferredOpen) { 1.74 + // See |@param aDeferOpen| in the JavaDoc comment for this function 1.75 + file.leafName = TRICKY_LEAF_NAME; 1.76 + } 1.77 + ostream.write("data", 4); 1.78 + if (aTrickDeferredOpen) { 1.79 + file.leafName = LEAF_NAME; 1.80 + } 1.81 + // We did a write, so the file should now exist 1.82 + do_check_true(file.clone().exists()); 1.83 + } 1.84 + ostream.close(); 1.85 + 1.86 + // Reading 1.87 + 1.88 + ensure_unique(file); 1.89 + let istream = Cc["@mozilla.org/network/file-input-stream;1"]. 1.90 + createInstance(Ci.nsIFileInputStream); 1.91 + var initOk, getOk; 1.92 + try { 1.93 + istream.init(file, -1, 0, aDeferOpen ? Ci.nsIFileInputStream.DEFER_OPEN : 0); 1.94 + initOk = true; 1.95 + } 1.96 + catch(e) { 1.97 + initOk = false; 1.98 + } 1.99 + try { 1.100 + let fstream = Cc["@mozilla.org/network/file-input-stream;1"]. 1.101 + createInstance(Ci.nsIFileInputStream); 1.102 + fstream.init(aFile, -1, 0, 0); 1.103 + getOk = true; 1.104 + } 1.105 + catch(e) { 1.106 + getOk = false; 1.107 + } 1.108 + 1.109 + // If the open is deferred, then Init should succeed even though the file we 1.110 + // intend to read does not exist, and then trying to read from it should 1.111 + // fail. The other case is where the open is not deferred, and there we should 1.112 + // get an error when we Init (and also when we try to read). 1.113 + do_check_true( (aDeferOpen && initOk && !getOk) || 1.114 + (!aDeferOpen && !initOk && !getOk) ); 1.115 + istream.close(); 1.116 +} 1.117 + 1.118 +/** 1.119 + * We test async operations in test_NetUtil.js, and here test for simple sync 1.120 + * operations on input streams. 1.121 + * 1.122 + * @param aDeferOpen 1.123 + * Whether to use DEFER_OPEN in the streams. 1.124 + */ 1.125 +function sync_operations(aDeferOpen) 1.126 +{ 1.127 + const TEST_DATA = "this is a test string"; 1.128 + const LEAF_NAME = "filestreams-test-file.tmp"; 1.129 + 1.130 + let file = Cc["@mozilla.org/file/directory_service;1"]. 1.131 + getService(Ci.nsIProperties). 1.132 + get("ProfD", Ci.nsIFile); 1.133 + file.append(LEAF_NAME); 1.134 + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); 1.135 + 1.136 + let ostream = Cc[OUTPUT_STREAM_CONTRACT_ID]. 1.137 + createInstance(Ci.nsIFileOutputStream); 1.138 + ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0); 1.139 + 1.140 + ostream.write(TEST_DATA, TEST_DATA.length); 1.141 + ostream.close(); 1.142 + 1.143 + let fstream = Cc["@mozilla.org/network/file-input-stream;1"]. 1.144 + createInstance(Ci.nsIFileInputStream); 1.145 + fstream.init(file, -1, 0, aDeferOpen ? Ci.nsIFileInputStream.DEFER_OPEN : 0); 1.146 + 1.147 + let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]. 1.148 + createInstance(Ci.nsIConverterInputStream); 1.149 + cstream.init(fstream, "UTF-8", 0, 0); 1.150 + 1.151 + let string = {}; 1.152 + cstream.readString(-1, string); 1.153 + cstream.close(); 1.154 + fstream.close(); 1.155 + 1.156 + do_check_eq(string.value, TEST_DATA); 1.157 +} 1.158 + 1.159 +//////////////////////////////////////////////////////////////////////////////// 1.160 +//// Tests 1.161 + 1.162 +function test_access() 1.163 +{ 1.164 + check_access(OUTPUT_STREAM_CONTRACT_ID, false, false); 1.165 +} 1.166 + 1.167 +function test_access_trick() 1.168 +{ 1.169 + check_access(OUTPUT_STREAM_CONTRACT_ID, false, true); 1.170 +} 1.171 + 1.172 +function test_access_defer() 1.173 +{ 1.174 + check_access(OUTPUT_STREAM_CONTRACT_ID, true, false); 1.175 +} 1.176 + 1.177 +function test_access_defer_trick() 1.178 +{ 1.179 + check_access(OUTPUT_STREAM_CONTRACT_ID, true, true); 1.180 +} 1.181 + 1.182 +function test_access_safe() 1.183 +{ 1.184 + check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, false, false); 1.185 +} 1.186 + 1.187 +function test_access_safe_trick() 1.188 +{ 1.189 + check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, false, true); 1.190 +} 1.191 + 1.192 +function test_access_safe_defer() 1.193 +{ 1.194 + check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, true, false); 1.195 +} 1.196 + 1.197 +function test_access_safe_defer_trick() 1.198 +{ 1.199 + check_access(SAFE_OUTPUT_STREAM_CONTRACT_ID, true, true); 1.200 +} 1.201 + 1.202 +function test_sync_operations() 1.203 +{ 1.204 + sync_operations(); 1.205 +} 1.206 + 1.207 +function test_sync_operations_deferred() 1.208 +{ 1.209 + sync_operations(true); 1.210 +} 1.211 + 1.212 +function do_test_zero_size_buffered(disableBuffering) 1.213 +{ 1.214 + const LEAF_NAME = "filestreams-test-file.tmp"; 1.215 + const BUFFERSIZE = 4096; 1.216 + 1.217 + let file = Cc["@mozilla.org/file/directory_service;1"]. 1.218 + getService(Ci.nsIProperties). 1.219 + get("ProfD", Ci.nsIFile); 1.220 + file.append(LEAF_NAME); 1.221 + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); 1.222 + 1.223 + let fstream = Cc["@mozilla.org/network/file-input-stream;1"]. 1.224 + createInstance(Ci.nsIFileInputStream); 1.225 + fstream.init(file, -1, 0, 1.226 + Ci.nsIFileInputStream.CLOSE_ON_EOF | 1.227 + Ci.nsIFileInputStream.REOPEN_ON_REWIND); 1.228 + 1.229 + var buffered = Cc["@mozilla.org/network/buffered-input-stream;1"]. 1.230 + createInstance(Ci.nsIBufferedInputStream); 1.231 + buffered.init(fstream, BUFFERSIZE); 1.232 + 1.233 + if (disableBuffering) { 1.234 + buffered.QueryInterface(Ci.nsIStreamBufferAccess).disableBuffering(); 1.235 + } 1.236 + 1.237 + // Scriptable input streams clamp read sizes to the return value of 1.238 + // available(), so don't quite do what we want here. 1.239 + let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]. 1.240 + createInstance(Ci.nsIConverterInputStream); 1.241 + cstream.init(buffered, "UTF-8", 0, 0); 1.242 + 1.243 + do_check_eq(buffered.available(), 0); 1.244 + 1.245 + // Now try reading from this stream 1.246 + let string = {}; 1.247 + do_check_eq(cstream.readString(BUFFERSIZE, string), 0); 1.248 + do_check_eq(string.value, ""); 1.249 + 1.250 + // Now check that available() throws 1.251 + var exceptionThrown = false; 1.252 + try { 1.253 + do_check_eq(buffered.available(), 0); 1.254 + } catch (e) { 1.255 + exceptionThrown = true; 1.256 + } 1.257 + do_check_true(exceptionThrown); 1.258 + 1.259 + // OK, now seek back to start 1.260 + buffered.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0); 1.261 + 1.262 + // Now check that available() does not throw 1.263 + exceptionThrown = false; 1.264 + try { 1.265 + do_check_eq(buffered.available(), 0); 1.266 + } catch (e) { 1.267 + exceptionThrown = true; 1.268 + } 1.269 + do_check_false(exceptionThrown); 1.270 +} 1.271 + 1.272 +function test_zero_size_buffered() 1.273 +{ 1.274 + do_test_zero_size_buffered(false); 1.275 + do_test_zero_size_buffered(true); 1.276 +} 1.277 + 1.278 +//////////////////////////////////////////////////////////////////////////////// 1.279 +//// Test Runner 1.280 + 1.281 +let tests = [ 1.282 + test_access, 1.283 + test_access_trick, 1.284 + test_access_defer, 1.285 + test_access_defer_trick, 1.286 + test_access_safe, 1.287 + test_access_safe_trick, 1.288 + test_access_safe_defer, 1.289 + test_access_safe_defer_trick, 1.290 + test_sync_operations, 1.291 + test_sync_operations_deferred, 1.292 + test_zero_size_buffered, 1.293 +]; 1.294 + 1.295 +function run_test() 1.296 +{ 1.297 + tests.forEach(function(test) { 1.298 + test(); 1.299 + }); 1.300 +} 1.301 +