toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 * http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 importScripts('worker_test_osfile_shared.js');
michael@0 5 importScripts("resource://gre/modules/workers/require.js");
michael@0 6
michael@0 7 let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
michael@0 8 SharedAll.Config.DEBUG = true;
michael@0 9
michael@0 10 function should_throw(f) {
michael@0 11 try {
michael@0 12 f();
michael@0 13 } catch (x) {
michael@0 14 return x;
michael@0 15 }
michael@0 16 return null;
michael@0 17 }
michael@0 18
michael@0 19 self.onmessage = function onmessage_start(msg) {
michael@0 20 self.onmessage = function onmessage_ignored(msg) {
michael@0 21 log("ignored message " + JSON.stringify(msg.data));
michael@0 22 };
michael@0 23 try {
michael@0 24 test_init();
michael@0 25 test_offsetby();
michael@0 26 test_open_existing_file();
michael@0 27 test_open_non_existing_file();
michael@0 28 test_flush_open_file();
michael@0 29 test_copy_existing_file();
michael@0 30 test_readall_writeall_file();
michael@0 31 test_position();
michael@0 32 test_move_file();
michael@0 33 test_iter_dir();
michael@0 34 test_info();
michael@0 35 test_path();
michael@0 36 test_exists_file();
michael@0 37 test_remove_file();
michael@0 38 } catch (x) {
michael@0 39 log("Catching error: " + x);
michael@0 40 log("Stack: " + x.stack);
michael@0 41 log("Source: " + x.toSource());
michael@0 42 ok(false, x.toString() + "\n" + x.stack);
michael@0 43 }
michael@0 44 finish();
michael@0 45 };
michael@0 46
michael@0 47 function test_init() {
michael@0 48 info("Starting test_init");
michael@0 49 importScripts("resource://gre/modules/osfile.jsm");
michael@0 50 }
michael@0 51
michael@0 52 function test_offsetby() {
michael@0 53 info("Starting test_offsetby");
michael@0 54
michael@0 55 // Initialize one array
michael@0 56 let LENGTH = 1024;
michael@0 57 let buf = new ArrayBuffer(LENGTH);
michael@0 58 let view = new Uint8Array(buf);
michael@0 59 let i;
michael@0 60 for (i = 0; i < LENGTH; ++i) {
michael@0 61 view[i] = i;
michael@0 62 }
michael@0 63
michael@0 64 // Walk through the array with offsetBy by 8 bits
michael@0 65 let uint8 = SharedAll.Type.uint8_t.in_ptr.implementation(buf);
michael@0 66 for (i = 0; i < LENGTH; ++i) {
michael@0 67 let value = SharedAll.offsetBy(uint8, i).contents;
michael@0 68 if (value != i%256) {
michael@0 69 is(value, i % 256, "test_offsetby: Walking through array with offsetBy (8 bits)");
michael@0 70 break;
michael@0 71 }
michael@0 72 }
michael@0 73
michael@0 74 // Walk again by 16 bits
michael@0 75 let uint16 = SharedAll.Type.uint16_t.in_ptr.implementation(buf);
michael@0 76 let view2 = new Uint16Array(buf);
michael@0 77 for (i = 0; i < LENGTH/2; ++i) {
michael@0 78 let value = SharedAll.offsetBy(uint16, i).contents;
michael@0 79 if (value != view2[i]) {
michael@0 80 is(value, view2[i], "test_offsetby: Walking through array with offsetBy (16 bits)");
michael@0 81 break;
michael@0 82 }
michael@0 83 }
michael@0 84
michael@0 85 // Ensure that offsetBy(..., 0) is idempotent
michael@0 86 let startptr = SharedAll.offsetBy(uint8, 0);
michael@0 87 let startptr2 = SharedAll.offsetBy(startptr, 0);
michael@0 88 is(startptr.toString(), startptr2.toString(), "test_offsetby: offsetBy(..., 0) is idmpotent");
michael@0 89
michael@0 90 // Ensure that offsetBy(ptr, ...) does not work if ptr is a void*
michael@0 91 let ptr = ctypes.voidptr_t(0);
michael@0 92 let exn;
michael@0 93 try {
michael@0 94 SharedAll.offsetBy(ptr, 1);
michael@0 95 } catch (x) {
michael@0 96 exn = x;
michael@0 97 }
michael@0 98 ok(!!exn, "test_offsetby: rejected offsetBy with void*");
michael@0 99
michael@0 100 info("test_offsetby: complete");
michael@0 101 }
michael@0 102
michael@0 103
michael@0 104 /**
michael@0 105 * Test that we can open an existing file.
michael@0 106 */
michael@0 107 function test_open_existing_file()
michael@0 108 {
michael@0 109 info("Starting test_open_existing");
michael@0 110 let file = OS.File.open("chrome/toolkit/components/osfile/tests/mochi/worker_test_osfile_unix.js");
michael@0 111 file.close();
michael@0 112 }
michael@0 113
michael@0 114 /**
michael@0 115 * Test that opening a file that does not exist fails with the right error.
michael@0 116 */
michael@0 117 function test_open_non_existing_file()
michael@0 118 {
michael@0 119 info("Starting test_open_non_existing");
michael@0 120 let exn;
michael@0 121 try {
michael@0 122 let file = OS.File.open("/I do not exist");
michael@0 123 } catch (x) {
michael@0 124 exn = x;
michael@0 125 info("test_open_non_existing_file: Exception detail " + exn);
michael@0 126 }
michael@0 127 ok(!!exn, "test_open_non_existing_file: Exception was raised ");
michael@0 128 ok(exn instanceof OS.File.Error, "test_open_non_existing_file: Exception was a OS.File.Error");
michael@0 129 ok(exn.becauseNoSuchFile, "test_open_non_existing_file: Exception confirms that the file does not exist");
michael@0 130 }
michael@0 131
michael@0 132 /**
michael@0 133 * Test that to ensure that |foo.flush()| does not
michael@0 134 * cause an error, where |foo| is an open file.
michael@0 135 */
michael@0 136 function test_flush_open_file()
michael@0 137 {
michael@0 138 info("Starting test_flush_open_file");
michael@0 139 let tmp = "test_flush.tmp";
michael@0 140 let file = OS.File.open(tmp, {create: true, write: true});
michael@0 141 file.flush();
michael@0 142 file.close();
michael@0 143 OS.File.remove(tmp);
michael@0 144 }
michael@0 145
michael@0 146 /**
michael@0 147 * Utility function for comparing two files (or a prefix of two files).
michael@0 148 *
michael@0 149 * This function returns nothing but fails of both files (or prefixes)
michael@0 150 * are not identical.
michael@0 151 *
michael@0 152 * @param {string} test The name of the test (used for logging).
michael@0 153 * @param {string} sourcePath The name of the first file.
michael@0 154 * @param {string} destPath The name of the second file.
michael@0 155 * @param {number=} prefix If specified, only compare the |prefix|
michael@0 156 * first bytes of |sourcePath| and |destPath|.
michael@0 157 */
michael@0 158 function compare_files(test, sourcePath, destPath, prefix)
michael@0 159 {
michael@0 160 info(test + ": Comparing " + sourcePath + " and " + destPath);
michael@0 161 let source = OS.File.open(sourcePath);
michael@0 162 let dest = OS.File.open(destPath);
michael@0 163 info("Files are open");
michael@0 164 let sourceResult, destResult;
michael@0 165 try {
michael@0 166 if (prefix != undefined) {
michael@0 167 sourceResult = source.read(prefix);
michael@0 168 destResult = dest.read(prefix);
michael@0 169 } else {
michael@0 170 sourceResult = source.read();
michael@0 171 destResult = dest.read();
michael@0 172 }
michael@0 173 is(sourceResult.length, destResult.length, test + ": Both files have the same size");
michael@0 174 for (let i = 0; i < sourceResult.length; ++i) {
michael@0 175 if (sourceResult[i] != destResult[i]) {
michael@0 176 is(sourceResult[i] != destResult[i], test + ": Comparing char " + i);
michael@0 177 break;
michael@0 178 }
michael@0 179 }
michael@0 180 } finally {
michael@0 181 source.close();
michael@0 182 dest.close();
michael@0 183 }
michael@0 184 info(test + ": Comparison complete");
michael@0 185 }
michael@0 186
michael@0 187 function test_readall_writeall_file()
michael@0 188 {
michael@0 189 let src_file_name =
michael@0 190 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi",
michael@0 191 "worker_test_osfile_front.js");
michael@0 192 let tmp_file_name =
michael@0 193 OS.Path.join(OS.Constants.Path.tmpDir, "test_osfile_front.tmp");
michael@0 194 info("Starting test_readall_writeall_file");
michael@0 195
michael@0 196 // read, ArrayBuffer
michael@0 197
michael@0 198 let source = OS.File.open(src_file_name);
michael@0 199 let dest = OS.File.open(tmp_file_name, {write: true, trunc:true});
michael@0 200 let size = source.stat().size;
michael@0 201
michael@0 202 let buf = new Uint8Array(size);
michael@0 203 let readResult = source.readTo(buf);
michael@0 204 is(readResult, size, "test_readall_writeall_file: read the right number of bytes");
michael@0 205
michael@0 206 dest.write(buf);
michael@0 207
michael@0 208 info("test_readall_writeall_file: copy complete (manual allocation)");
michael@0 209 source.close();
michael@0 210 dest.close();
michael@0 211
michael@0 212 compare_files("test_readall_writeall_file (manual allocation)", src_file_name, tmp_file_name);
michael@0 213 OS.File.remove(tmp_file_name);
michael@0 214
michael@0 215 // read, C buffer
michael@0 216 source = OS.File.open(src_file_name);
michael@0 217 dest = OS.File.open(tmp_file_name, {write: true, trunc:true});
michael@0 218 buf = new ArrayBuffer(size);
michael@0 219 let ptr = OS.Shared.Type.voidptr_t.implementation(buf);
michael@0 220 readResult = source.readTo(ptr, {bytes: size});
michael@0 221 is(readResult, size, "test_readall_writeall_file: read the right number of bytes (C buffer)");
michael@0 222
michael@0 223 dest.write(ptr, {bytes: size});
michael@0 224
michael@0 225 info("test_readall_writeall_file: copy complete (C buffer)");
michael@0 226 source.close();
michael@0 227 dest.close();
michael@0 228
michael@0 229 compare_files("test_readall_writeall_file (C buffer)", src_file_name, tmp_file_name);
michael@0 230 OS.File.remove(tmp_file_name);
michael@0 231
michael@0 232 // read/write, C buffer, missing |bytes| option
michael@0 233 source = OS.File.open(src_file_name);
michael@0 234 dest = OS.File.open(tmp_file_name, {write: true, trunc:true});
michael@0 235 let exn = should_throw(function() { source.readTo(ptr); });
michael@0 236 ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: read with C pointer and without bytes fails with the correct error");
michael@0 237 exn = should_throw(function() { dest.write(ptr); });
michael@0 238 ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: write with C pointer and without bytes fails with the correct error");
michael@0 239
michael@0 240 source.close();
michael@0 241 dest.close();
michael@0 242
michael@0 243 // readTo, ArrayBuffer + offset
michael@0 244 let OFFSET = 12;
michael@0 245 let LEFT = size - OFFSET;
michael@0 246 buf = new ArrayBuffer(size);
michael@0 247 let offset_view = new Uint8Array(buf, OFFSET);
michael@0 248 source = OS.File.open(src_file_name);
michael@0 249 dest = OS.File.open(tmp_file_name, {write: true, trunc:true});
michael@0 250
michael@0 251 readResult = source.readTo(offset_view);
michael@0 252 is(readResult, LEFT, "test_readall_writeall_file: read the right number of bytes (with offset)");
michael@0 253
michael@0 254 dest.write(offset_view);
michael@0 255 is(dest.stat().size, LEFT, "test_readall_writeall_file: wrote the right number of bytes (with offset)");
michael@0 256
michael@0 257 info("test_readall_writeall_file: copy complete (with offset)");
michael@0 258 source.close();
michael@0 259 dest.close();
michael@0 260
michael@0 261 compare_files("test_readall_writeall_file (with offset)", src_file_name, tmp_file_name, LEFT);
michael@0 262 OS.File.remove(tmp_file_name);
michael@0 263
michael@0 264 // read
michael@0 265 buf = new Uint8Array(size);
michael@0 266 source = OS.File.open(src_file_name);
michael@0 267 dest = OS.File.open(tmp_file_name, {write: true, trunc:true});
michael@0 268
michael@0 269 readResult = source.read();
michael@0 270 is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (auto allocation)");
michael@0 271
michael@0 272 dest.write(readResult);
michael@0 273
michael@0 274 info("test_readall_writeall_file: copy complete (auto allocation)");
michael@0 275 source.close();
michael@0 276 dest.close();
michael@0 277
michael@0 278 compare_files("test_readall_writeall_file (auto allocation)", src_file_name, tmp_file_name);
michael@0 279 OS.File.remove(tmp_file_name);
michael@0 280
michael@0 281 // File.readAll
michael@0 282 readResult = OS.File.read(src_file_name);
michael@0 283 is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (OS.File.readAll)");
michael@0 284
michael@0 285 // File.writeAtomic on top of nothing
michael@0 286 OS.File.writeAtomic(tmp_file_name, readResult,
michael@0 287 {tmpPath: tmp_file_name + ".tmp"});
michael@0 288 try {
michael@0 289 let stat = OS.File.stat(tmp_file_name);
michael@0 290 info("readAll + writeAtomic created a file");
michael@0 291 is(stat.size, size, "readAll + writeAtomic created a file of the right size");
michael@0 292 } catch (x) {
michael@0 293 ok(false, "readAll + writeAtomic somehow failed");
michael@0 294 if(x.becauseNoSuchFile) {
michael@0 295 ok(false, "readAll + writeAtomic did not create file");
michael@0 296 }
michael@0 297 }
michael@0 298 compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic)",
michael@0 299 src_file_name, tmp_file_name);
michael@0 300 exn = null;
michael@0 301 try {
michael@0 302 let stat = OS.File.stat(tmp_file_name + ".tmp");
michael@0 303 } catch (x) {
michael@0 304 exn = x;
michael@0 305 }
michael@0 306 ok(!!exn, "readAll + writeAtomic cleaned up after itself");
michael@0 307
michael@0 308 // File.writeAtomic on top of existing file
michael@0 309 // Remove content and set arbitrary size, to avoid potential false negatives
michael@0 310 dest = OS.File.open(tmp_file_name, {write: true, trunc:true});
michael@0 311 dest.setPosition(1234);
michael@0 312 dest.close();
michael@0 313
michael@0 314 OS.File.writeAtomic(tmp_file_name, readResult,
michael@0 315 {tmpPath: tmp_file_name + ".tmp"});
michael@0 316 compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic 2)",
michael@0 317 src_file_name, tmp_file_name);
michael@0 318
michael@0 319 // File.writeAtomic on top of existing file but without overwritten the file
michael@0 320 exn = null;
michael@0 321 try {
michael@0 322 let view = new Uint8Array(readResult.buffer, 10, 200);
michael@0 323 OS.File.writeAtomic(tmp_file_name, view,
michael@0 324 { tmpPath: tmp_file_name + ".tmp", noOverwrite: true});
michael@0 325 } catch (x) {
michael@0 326 exn = x;
michael@0 327 }
michael@0 328 ok(exn && exn instanceof OS.File.Error && exn.becauseExists, "writeAtomic fails if file already exists with noOverwrite option");
michael@0 329 // Check file was not overwritten.
michael@0 330 compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic check file was not overwritten)",
michael@0 331 src_file_name, tmp_file_name);
michael@0 332
michael@0 333 // Ensure that File.writeAtomic fails if no temporary file name is provided
michael@0 334 // (FIXME: Remove this test as part of bug 793660)
michael@0 335
michael@0 336 exn = null;
michael@0 337 try {
michael@0 338 OS.File.writeAtomic(tmp_file_name, readResult.buffer,
michael@0 339 {bytes: readResult.length});
michael@0 340 } catch (x) {
michael@0 341 exn = x;
michael@0 342 }
michael@0 343 ok(!!exn && exn instanceof TypeError, "writeAtomic fails if tmpPath is not provided");
michael@0 344
michael@0 345 // Check that writeAtomic fails when destination path is undefined
michael@0 346 exn = null;
michael@0 347 try {
michael@0 348 let path = undefined;
michael@0 349 let options = {tmpPath: tmp_file_name};
michael@0 350 OS.File.writeAtomic(path, readResult.buffer, options);
michael@0 351 } catch (x) {
michael@0 352 exn = x;
michael@0 353 }
michael@0 354 ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is undefined");
michael@0 355
michael@0 356 // Check that writeAtomic fails when destination path is an empty string
michael@0 357 exn = null;
michael@0 358 try {
michael@0 359 let path = "";
michael@0 360 let options = {tmpPath: tmp_file_name};
michael@0 361 OS.File.writeAtomic(path, readResult.buffer, options);
michael@0 362 } catch (x) {
michael@0 363 exn = x;
michael@0 364 }
michael@0 365 ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is an empty string");
michael@0 366
michael@0 367 // Cleanup.
michael@0 368 OS.File.remove(tmp_file_name);
michael@0 369 }
michael@0 370
michael@0 371 /**
michael@0 372 * Test that copying a file using |copy| works.
michael@0 373 */
michael@0 374 function test_copy_existing_file()
michael@0 375 {
michael@0 376 let src_file_name =
michael@0 377 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi",
michael@0 378 "worker_test_osfile_front.js");
michael@0 379 let tmp_file_name = "test_osfile_front.tmp";
michael@0 380 info("Starting test_copy_existing");
michael@0 381 OS.File.copy(src_file_name, tmp_file_name);
michael@0 382
michael@0 383 info("test_copy_existing: Copy complete");
michael@0 384 compare_files("test_copy_existing", src_file_name, tmp_file_name);
michael@0 385
michael@0 386 // Create a bogus file with arbitrary content, then attempt to overwrite
michael@0 387 // it with |copy|.
michael@0 388 let dest = OS.File.open(tmp_file_name, {trunc: true});
michael@0 389 let buf = new Uint8Array(50);
michael@0 390 dest.write(buf);
michael@0 391 dest.close();
michael@0 392
michael@0 393 OS.File.copy(src_file_name, tmp_file_name);
michael@0 394
michael@0 395 compare_files("test_copy_existing 2", src_file_name, tmp_file_name);
michael@0 396
michael@0 397 // Attempt to overwrite with noOverwrite
michael@0 398 let exn;
michael@0 399 try {
michael@0 400 OS.File.copy(src_file_name, tmp_file_name, {noOverwrite: true});
michael@0 401 } catch(x) {
michael@0 402 exn = x;
michael@0 403 }
michael@0 404 ok(!!exn, "test_copy_existing: noOverwrite prevents overwriting existing files");
michael@0 405
michael@0 406 info("test_copy_existing: Cleaning up");
michael@0 407 OS.File.remove(tmp_file_name);
michael@0 408 }
michael@0 409
michael@0 410 /**
michael@0 411 * Test that moving a file works.
michael@0 412 */
michael@0 413 function test_move_file()
michael@0 414 {
michael@0 415 info("test_move_file: Starting");
michael@0 416 // 1. Copy file into a temporary file
michael@0 417 let src_file_name =
michael@0 418 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi",
michael@0 419 "worker_test_osfile_front.js");
michael@0 420 let tmp_file_name = "test_osfile_front.tmp";
michael@0 421 let tmp2_file_name = "test_osfile_front.tmp2";
michael@0 422 OS.File.copy(src_file_name, tmp_file_name);
michael@0 423
michael@0 424 info("test_move_file: Copy complete");
michael@0 425
michael@0 426 // 2. Move
michael@0 427 OS.File.move(tmp_file_name, tmp2_file_name);
michael@0 428
michael@0 429 info("test_move_file: Move complete");
michael@0 430
michael@0 431 // 3. Check that destination exists
michael@0 432 compare_files("test_move_file", src_file_name, tmp2_file_name);
michael@0 433
michael@0 434 // 4. Check that original file does not exist anymore
michael@0 435 let exn;
michael@0 436 try {
michael@0 437 OS.File.open(tmp_file_name);
michael@0 438 } catch (x) {
michael@0 439 exn = x;
michael@0 440 }
michael@0 441 ok(!!exn, "test_move_file: Original file has been removed");
michael@0 442
michael@0 443 info("test_move_file: Cleaning up");
michael@0 444 OS.File.remove(tmp2_file_name);
michael@0 445 }
michael@0 446
michael@0 447 function test_iter_dir()
michael@0 448 {
michael@0 449 info("test_iter_dir: Starting");
michael@0 450
michael@0 451 // Create a file, to be sure that it exists
michael@0 452 let tmp_file_name = "test_osfile_front.tmp";
michael@0 453 let tmp_file = OS.File.open(tmp_file_name, {write: true, trunc:true});
michael@0 454 tmp_file.close();
michael@0 455
michael@0 456 let parent = OS.File.getCurrentDirectory();
michael@0 457 info("test_iter_dir: directory " + parent);
michael@0 458 let iterator = new OS.File.DirectoryIterator(parent);
michael@0 459 info("test_iter_dir: iterator created");
michael@0 460 let encountered_tmp_file = false;
michael@0 461 for (let entry in iterator) {
michael@0 462 // Checking that |name| can be decoded properly
michael@0 463 info("test_iter_dir: encountering entry " + entry.name);
michael@0 464
michael@0 465 if (entry.name == tmp_file_name) {
michael@0 466 encountered_tmp_file = true;
michael@0 467 isnot(entry.isDir, "test_iter_dir: The temporary file is not a directory");
michael@0 468 isnot(entry.isSymLink, "test_iter_dir: The temporary file is not a link");
michael@0 469 }
michael@0 470
michael@0 471 let file;
michael@0 472 let success = true;
michael@0 473 try {
michael@0 474 file = OS.File.open(entry.path);
michael@0 475 } catch (x) {
michael@0 476 if (x.becauseNoSuchFile) {
michael@0 477 success = false;
michael@0 478 }
michael@0 479 }
michael@0 480 if (file) {
michael@0 481 file.close();
michael@0 482 }
michael@0 483 ok(success, "test_iter_dir: Entry " + entry.path + " exists");
michael@0 484
michael@0 485 if (OS.Win) {
michael@0 486 let year = new Date().getFullYear();
michael@0 487 let creation = entry.winCreationDate;
michael@0 488 ok(creation, "test_iter_dir: Windows creation date exists: " + creation);
michael@0 489 ok(creation.getFullYear() >= year - 1 && creation.getFullYear() <= year, "test_iter_dir: consistent creation date");
michael@0 490
michael@0 491 let lastWrite = entry.winLastWriteDate;
michael@0 492 ok(lastWrite, "test_iter_dir: Windows lastWrite date exists: " + lastWrite);
michael@0 493 ok(lastWrite.getFullYear() >= year - 1 && lastWrite.getFullYear() <= year, "test_iter_dir: consistent lastWrite date");
michael@0 494
michael@0 495 let lastAccess = entry.winLastAccessDate;
michael@0 496 ok(lastAccess, "test_iter_dir: Windows lastAccess date exists: " + lastAccess);
michael@0 497 ok(lastAccess.getFullYear() >= year - 1 && lastAccess.getFullYear() <= year, "test_iter_dir: consistent lastAccess date");
michael@0 498 }
michael@0 499
michael@0 500 }
michael@0 501 ok(encountered_tmp_file, "test_iter_dir: We have found the temporary file");
michael@0 502
michael@0 503 info("test_iter_dir: Cleaning up");
michael@0 504 iterator.close();
michael@0 505
michael@0 506 // Testing nextBatch()
michael@0 507 iterator = new OS.File.DirectoryIterator(parent);
michael@0 508 let allentries = [x for(x in iterator)];
michael@0 509 iterator.close();
michael@0 510
michael@0 511 ok(allentries.length >= 14, "test_iter_dir: Meta-check: the test directory should contain at least 14 items");
michael@0 512
michael@0 513 iterator = new OS.File.DirectoryIterator(parent);
michael@0 514 let firstten = iterator.nextBatch(10);
michael@0 515 is(firstten.length, 10, "test_iter_dir: nextBatch(10) returns 10 items");
michael@0 516 for (let i = 0; i < firstten.length; ++i) {
michael@0 517 is(allentries[i].path, firstten[i].path, "test_iter_dir: Checking that batch returns the correct entries");
michael@0 518 }
michael@0 519 let nextthree = iterator.nextBatch(3);
michael@0 520 is(nextthree.length, 3, "test_iter_dir: nextBatch(3) returns 3 items");
michael@0 521 for (let i = 0; i < nextthree.length; ++i) {
michael@0 522 is(allentries[i + firstten.length].path, nextthree[i].path, "test_iter_dir: Checking that batch 2 returns the correct entries");
michael@0 523 }
michael@0 524 let everythingelse = iterator.nextBatch();
michael@0 525 ok(everythingelse.length >= 1, "test_iter_dir: nextBatch() returns at least one item");
michael@0 526 for (let i = 0; i < everythingelse.length; ++i) {
michael@0 527 is(allentries[i + firstten.length + nextthree.length].path, everythingelse[i].path, "test_iter_dir: Checking that batch 3 returns the correct entries");
michael@0 528 }
michael@0 529 is(iterator.nextBatch().length, 0, "test_iter_dir: Once there is nothing left, nextBatch returns an empty array");
michael@0 530 iterator.close();
michael@0 531
michael@0 532 iterator = new OS.File.DirectoryIterator(parent);
michael@0 533 iterator.close();
michael@0 534 is(iterator.nextBatch().length, 0, "test_iter_dir: nextBatch on closed iterator returns an empty array");
michael@0 535
michael@0 536 iterator = new OS.File.DirectoryIterator(parent);
michael@0 537 let allentries2 = iterator.nextBatch();
michael@0 538 is(allentries.length, allentries2.length, "test_iter_dir: Checking that getBatch(null) returns the right number of entries");
michael@0 539 for (let i = 0; i < allentries.length; ++i) {
michael@0 540 is(allentries[i].path, allentries2[i].path, "test_iter_dir: Checking that getBatch(null) returns everything in the right order");
michael@0 541 }
michael@0 542 iterator.close();
michael@0 543
michael@0 544 // Test forEach
michael@0 545 iterator = new OS.File.DirectoryIterator(parent);
michael@0 546 let index = 0;
michael@0 547 iterator.forEach(
michael@0 548 function cb(entry, aIndex, aIterator) {
michael@0 549 is(index, aIndex, "test_iter_dir: Checking that forEach index is correct");
michael@0 550 ok(iterator == aIterator, "test_iter_dir: Checking that right iterator is passed");
michael@0 551 if (index < 10) {
michael@0 552 is(allentries[index].path, entry.path, "test_iter_dir: Checking that forEach entry is correct");
michael@0 553 } else if (index == 10) {
michael@0 554 iterator.close();
michael@0 555 } else {
michael@0 556 ok(false, "test_iter_dir: Checking that forEach can be stopped early");
michael@0 557 }
michael@0 558 ++index;
michael@0 559 });
michael@0 560 iterator.close();
michael@0 561
michael@0 562 //test for prototype |OS.File.DirectoryIterator.unixAsFile|
michael@0 563 if ("unixAsFile" in OS.File.DirectoryIterator.prototype) {
michael@0 564 info("testing property unixAsFile");
michael@0 565 let path = OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi");
michael@0 566 iterator = new OS.File.DirectoryIterator(path);
michael@0 567
michael@0 568 let dir_file = iterator.unixAsFile();// return |File|
michael@0 569 let stat0 = dir_file.stat();
michael@0 570 let stat1 = OS.File.stat(path);
michael@0 571
michael@0 572 let unix_info_to_string = function unix_info_to_string(info) {
michael@0 573 return "| " + info.unixMode + " | " + info.unixOwner + " | " + info.unixGroup + " | " + info.creationDate + " | " + info.lastModificationDate + " | " + info.lastAccessDate + " | " + info.size + " |";
michael@0 574 };
michael@0 575
michael@0 576 let s0_string = unix_info_to_string(stat0);
michael@0 577 let s1_string = unix_info_to_string(stat1);
michael@0 578
michael@0 579 ok(stat0.isDir, "unixAsFile returned a directory");
michael@0 580 is(s0_string, s1_string, "unixAsFile returned the correct file");
michael@0 581 dir_file.close();
michael@0 582 iterator.close();
michael@0 583 }
michael@0 584 info("test_iter_dir: Complete");
michael@0 585 }
michael@0 586
michael@0 587 function test_position() {
michael@0 588 info("test_position: Starting");
michael@0 589
michael@0 590 ok("POS_START" in OS.File, "test_position: POS_START exists");
michael@0 591 ok("POS_CURRENT" in OS.File, "test_position: POS_CURRENT exists");
michael@0 592 ok("POS_END" in OS.File, "test_position: POS_END exists");
michael@0 593
michael@0 594 let ARBITRARY_POSITION = 321;
michael@0 595 let src_file_name =
michael@0 596 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi",
michael@0 597 "worker_test_osfile_front.js");
michael@0 598
michael@0 599 let file = OS.File.open(src_file_name);
michael@0 600 is(file.getPosition(), 0, "test_position: Initial position is 0");
michael@0 601
michael@0 602 let size = 0 + file.stat().size; // Hack: We can remove this 0 + once 776259 has landed
michael@0 603
michael@0 604 file.setPosition(ARBITRARY_POSITION, OS.File.POS_START);
michael@0 605 is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position from start");
michael@0 606
michael@0 607 file.setPosition(0, OS.File.POS_START);
michael@0 608 is(file.getPosition(), 0, "test_position: Setting position from start back to 0");
michael@0 609
michael@0 610 file.setPosition(ARBITRARY_POSITION);
michael@0 611 is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position without argument");
michael@0 612
michael@0 613 file.setPosition(-ARBITRARY_POSITION, OS.File.POS_END);
michael@0 614 is(file.getPosition(), size - ARBITRARY_POSITION, "test_position: Setting position from end");
michael@0 615
michael@0 616 file.setPosition(ARBITRARY_POSITION, OS.File.POS_CURRENT);
michael@0 617 is(file.getPosition(), size, "test_position: Setting position from current");
michael@0 618
michael@0 619 file.close();
michael@0 620 info("test_position: Complete");
michael@0 621 }
michael@0 622
michael@0 623 function test_info() {
michael@0 624 info("test_info: Starting");
michael@0 625
michael@0 626 let filename = "test_info.tmp";
michael@0 627 let size = 261;// An arbitrary file length
michael@0 628 let start = new Date();
michael@0 629
michael@0 630 // Cleanup any leftover from previous tests
michael@0 631 try {
michael@0 632 OS.File.remove(filename);
michael@0 633 info("test_info: Cleaned up previous garbage");
michael@0 634 } catch (x) {
michael@0 635 if (!x.becauseNoSuchFile) {
michael@0 636 throw x;
michael@0 637 }
michael@0 638 info("test_info: No previous garbage");
michael@0 639 }
michael@0 640
michael@0 641 let file = OS.File.open(filename, {trunc: true});
michael@0 642 let buf = new ArrayBuffer(size);
michael@0 643 file._write(buf, size);
michael@0 644 file.close();
michael@0 645
michael@0 646 // Test OS.File.stat on new file
michael@0 647 let stat = OS.File.stat(filename);
michael@0 648 ok(!!stat, "test_info: info acquired");
michael@0 649 ok(!stat.isDir, "test_info: file is not a directory");
michael@0 650 is(stat.isSymLink, false, "test_info: file is not a link");
michael@0 651 is(stat.size.toString(), size, "test_info: correct size");
michael@0 652
michael@0 653 let stop = new Date();
michael@0 654
michael@0 655 // We round down/up by 1s as file system precision is lower than
michael@0 656 // Date precision (no clear specifications about that, but it seems
michael@0 657 // that this can be a little over 1 second under ext3 and 2 seconds
michael@0 658 // under FAT).
michael@0 659 let SLOPPY_FILE_SYSTEM_ADJUSTMENT = 3000;
michael@0 660 let startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT;
michael@0 661 let stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT;
michael@0 662 info("Testing stat with bounds [ " + startMs + ", " + stopMs +" ]");
michael@0 663
michael@0 664 (function() {
michael@0 665 let birth;
michael@0 666 if ("winBirthDate" in stat) {
michael@0 667 birth = stat.winBirthDate;
michael@0 668 } else if ("macBirthDate" in stat) {
michael@0 669 birth = stat.macBirthDate;
michael@0 670 } else {
michael@0 671 ok(true, "Skipping birthdate test");
michael@0 672 return;
michael@0 673 }
michael@0 674 ok(birth.getTime() <= stopMs,
michael@0 675 "test_info: platformBirthDate is consistent");
michael@0 676 // Note: Previous versions of this test checked whether the file
michael@0 677 // has been created after the start of the test. Unfortunately,
michael@0 678 // this sometimes failed under Windows, in specific circumstances:
michael@0 679 // if the file has been removed at the start of the test and
michael@0 680 // recreated immediately, the Windows file system detects this and
michael@0 681 // decides that the file was actually truncated rather than
michael@0 682 // recreated, hence that it should keep its previous creation
michael@0 683 // date. Debugging hilarity ensues.
michael@0 684 });
michael@0 685
michael@0 686 let change = stat.lastModificationDate;
michael@0 687 info("Testing lastModificationDate: " + change);
michael@0 688 ok(change.getTime() >= startMs && change.getTime() <= stopMs,
michael@0 689 "test_info: lastModificationDate is consistent");
michael@0 690
michael@0 691 // Test OS.File.prototype.stat on new file
michael@0 692 file = OS.File.open(filename);
michael@0 693 try {
michael@0 694 stat = file.stat();
michael@0 695 } finally {
michael@0 696 file.close();
michael@0 697 }
michael@0 698
michael@0 699 ok(!!stat, "test_info: info acquired 2");
michael@0 700 ok(!stat.isDir, "test_info: file is not a directory 2");
michael@0 701 ok(!stat.isSymLink, "test_info: file is not a link 2");
michael@0 702 is(stat.size.toString(), size, "test_info: correct size 2");
michael@0 703
michael@0 704 stop = new Date();
michael@0 705
michael@0 706 // Round up/down as above
michael@0 707 startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT;
michael@0 708 stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT;
michael@0 709 info("Testing stat 2 with bounds [ " + startMs + ", " + stopMs +" ]");
michael@0 710
michael@0 711 let access = stat.lastAccessDate;
michael@0 712 info("Testing lastAccessDate: " + access);
michael@0 713 ok(access.getTime() >= startMs && access.getTime() <= stopMs,
michael@0 714 "test_info: lastAccessDate is consistent");
michael@0 715
michael@0 716 change = stat.lastModificationDate;
michael@0 717 info("Testing lastModificationDate 2: " + change);
michael@0 718 ok(change.getTime() >= startMs && change.getTime() <= stopMs,
michael@0 719 "test_info: lastModificationDate 2 is consistent");
michael@0 720
michael@0 721 // Test OS.File.stat on directory
michael@0 722 stat = OS.File.stat(OS.File.getCurrentDirectory());
michael@0 723 ok(!!stat, "test_info: info on directory acquired");
michael@0 724 ok(stat.isDir, "test_info: directory is a directory");
michael@0 725
michael@0 726 info("test_info: Complete");
michael@0 727 }
michael@0 728
michael@0 729 // Note that most of the features of path are tested in
michael@0 730 // worker_test_osfile_{unix, win}.js
michael@0 731 function test_path()
michael@0 732 {
michael@0 733 info("test_path: starting");
michael@0 734 let abcd = OS.Path.join("a", "b", "c", "d");
michael@0 735 is(OS.Path.basename(abcd), "d", "basename of a/b/c/d");
michael@0 736
michael@0 737 let abc = OS.Path.join("a", "b", "c");
michael@0 738 is(OS.Path.dirname(abcd), abc, "dirname of a/b/c/d");
michael@0 739
michael@0 740 let abdotsc = OS.Path.join("a", "b", "..", "c");
michael@0 741 is(OS.Path.normalize(abdotsc), OS.Path.join("a", "c"), "normalize a/b/../c");
michael@0 742
michael@0 743 let adotsdotsdots = OS.Path.join("a", "..", "..", "..");
michael@0 744 is(OS.Path.normalize(adotsdotsdots), OS.Path.join("..", ".."), "normalize a/../../..");
michael@0 745
michael@0 746 info("test_path: Complete");
michael@0 747 }
michael@0 748
michael@0 749 /**
michael@0 750 * Test the file |exists| method.
michael@0 751 */
michael@0 752 function test_exists_file()
michael@0 753 {
michael@0 754 let file_name = OS.Path.join("chrome", "toolkit", "components" ,"osfile",
michael@0 755 "tests", "mochi", "test_osfile_front.xul");
michael@0 756 info("test_exists_file: starting");
michael@0 757 ok(OS.File.exists(file_name), "test_exists_file: file exists (OS.File.exists)");
michael@0 758 ok(!OS.File.exists(file_name + ".tmp"), "test_exists_file: file does not exists (OS.File.exists)");
michael@0 759
michael@0 760 let dir_name = OS.Path.join("chrome", "toolkit", "components" ,"osfile",
michael@0 761 "tests", "mochi");
michael@0 762 ok(OS.File.exists(dir_name), "test_exists_file: directory exists");
michael@0 763 ok(!OS.File.exists(dir_name) + ".tmp", "test_exists_file: directory does not exist");
michael@0 764
michael@0 765 info("test_exists_file: complete");
michael@0 766 }
michael@0 767
michael@0 768 /**
michael@0 769 * Test the file |remove| method.
michael@0 770 */
michael@0 771 function test_remove_file()
michael@0 772 {
michael@0 773 let absent_file_name = "test_osfile_front_absent.tmp";
michael@0 774
michael@0 775 // Check that removing absent files is handled correctly
michael@0 776 let exn = should_throw(function() {
michael@0 777 OS.File.remove(absent_file_name, {ignoreAbsent: false});
michael@0 778 });
michael@0 779 ok(!!exn, "test_remove_file: throws if there is no such file");
michael@0 780
michael@0 781 exn = should_throw(function() {
michael@0 782 OS.File.remove(absent_file_name, {ignoreAbsent: true});
michael@0 783 OS.File.remove(absent_file_name);
michael@0 784 });
michael@0 785 ok(!exn, "test_remove_file: ignoreAbsent works");
michael@0 786
michael@0 787 if (OS.Win) {
michael@0 788 let file_name = "test_osfile_front_file_to_remove.tmp";
michael@0 789 let file = OS.File.open(file_name, {write: true});
michael@0 790 file.close();
michael@0 791 ok(OS.File.exists(file_name), "test_remove_file: test file exists");
michael@0 792 OS.Win.File.SetFileAttributes(file_name,
michael@0 793 OS.Constants.Win.FILE_ATTRIBUTE_READONLY);
michael@0 794 OS.File.remove(file_name);
michael@0 795 ok(!OS.File.exists(file_name),
michael@0 796 "test_remove_file: test file has been removed");
michael@0 797 }
michael@0 798 }

mercurial