addon-sdk/source/test/test-fs.js

branch
TOR_BUG_9701
changeset 10
ac0c01689b40
equal deleted inserted replaced
-1:000000000000 0:1a61d805a443
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 const { pathFor, platform } = require("sdk/system");
8 const fs = require("sdk/io/fs");
9 const url = require("sdk/url");
10 const path = require("sdk/fs/path");
11 const { defer } = require("sdk/core/promise");
12 const { Buffer } = require("sdk/io/buffer");
13 const { is } = require("sdk/system/xul-app");
14
15 // Use profile directory to list / read / write files.
16 const profilePath = pathFor("ProfD");
17 const fileNameInProfile = "compatibility.ini";
18 const dirNameInProfile = "extensions";
19 const filePathInProfile = path.join(profilePath, fileNameInProfile);
20 const dirPathInProfile = path.join(profilePath, dirNameInProfile);
21 const mkdirPath = path.join(profilePath, "sdk-fixture-mkdir");
22 const writePath = path.join(profilePath, "sdk-fixture-writeFile");
23 const unlinkPath = path.join(profilePath, "sdk-fixture-unlink");
24 const truncatePath = path.join(profilePath, "sdk-fixture-truncate");
25 const renameFromPath = path.join(profilePath, "sdk-fixture-rename-from");
26 const renameToPath = path.join(profilePath, "sdk-fixture-rename-to");
27 const chmodPath = path.join(profilePath, "sdk-fixture-chmod");
28
29 const profileEntries = [
30 "compatibility.ini",
31 "extensions",
32 "prefs.js"
33 // There are likely to be a lot more files but we can"t really
34 // on consistent list so we limit to this.
35 ];
36
37 const isWindows = platform.indexOf('win') === 0;
38
39 exports["test readdir"] = function(assert, end) {
40 var async = false;
41 fs.readdir(profilePath, function(error, entries) {
42 assert.ok(async, "readdir is async");
43 assert.ok(!error, "there is no error when reading directory");
44 assert.ok(profileEntries.length <= entries.length,
45 "got at least number of entries we expect");
46 assert.ok(profileEntries.every(function(entry) {
47 return entries.indexOf(entry) >= 0;
48 }), "all profiles are present");
49 end();
50 });
51
52 async = true;
53 };
54
55 exports["test readdir error"] = function(assert, end) {
56 var async = false;
57 var path = profilePath + "-does-not-exists";
58 fs.readdir(path, function(error, entries) {
59 assert.ok(async, "readdir is async");
60 assert.equal(error.message, "ENOENT, readdir " + path);
61 assert.equal(error.code, "ENOENT", "error has a code");
62 assert.equal(error.path, path, "error has a path");
63 assert.equal(error.errno, 34, "error has a errno");
64 end();
65 });
66
67 async = true;
68 };
69
70 exports["test readdirSync"] = function(assert) {
71 var async = false;
72 var entries = fs.readdirSync(profilePath);
73 assert.ok(profileEntries.length <= entries.length,
74 "got at least number of entries we expect");
75 assert.ok(profileEntries.every(function(entry) {
76 return entries.indexOf(entry) >= 0;
77 }), "all profiles are present");
78 };
79
80 exports["test readdirSync error"] = function(assert) {
81 var async = false;
82 var path = profilePath + "-does-not-exists";
83 try {
84 fs.readdirSync(path);
85 assert.fail(Error("No error was thrown"));
86 } catch (error) {
87 assert.equal(error.message, "ENOENT, readdir " + path);
88 assert.equal(error.code, "ENOENT", "error has a code");
89 assert.equal(error.path, path, "error has a path");
90 assert.equal(error.errno, 34, "error has a errno");
91 }
92 };
93
94 exports["test readFile"] = function(assert, end) {
95 let async = false;
96 fs.readFile(filePathInProfile, function(error, content) {
97 assert.ok(async, "readFile is async");
98 assert.ok(!error, "error is falsy");
99
100 assert.ok(Buffer.isBuffer(content), "readFile returns buffer");
101 assert.ok(typeof(content.length) === "number", "buffer has length");
102 assert.ok(content.toString().indexOf("[Compatibility]") >= 0,
103 "content contains expected data");
104 end();
105 });
106 async = true;
107 };
108
109 exports["test readFile error"] = function(assert, end) {
110 let async = false;
111 let path = filePathInProfile + "-does-not-exists";
112 fs.readFile(path, function(error, content) {
113 assert.ok(async, "readFile is async");
114 assert.equal(error.message, "ENOENT, open " + path);
115 assert.equal(error.code, "ENOENT", "error has a code");
116 assert.equal(error.path, path, "error has a path");
117 assert.equal(error.errno, 34, "error has a errno");
118
119 end();
120 });
121 async = true;
122 };
123
124 exports["test readFileSync not implemented"] = function(assert) {
125 let buffer = fs.readFileSync(filePathInProfile);
126 assert.ok(buffer.toString().indexOf("[Compatibility]") >= 0,
127 "read content");
128 };
129
130 exports["test fs.stat file"] = function(assert, end) {
131 let async = false;
132 let path = filePathInProfile;
133 fs.stat(path, function(error, stat) {
134 assert.ok(async, "fs.stat is async");
135 assert.ok(!error, "error is falsy");
136 assert.ok(!stat.isDirectory(), "not a dir");
137 assert.ok(stat.isFile(), "is a file");
138 assert.ok(!stat.isSymbolicLink(), "isn't a symlink");
139 assert.ok(typeof(stat.size) === "number", "size is a number");
140 assert.ok(stat.exists === true, "file exists");
141 assert.ok(typeof(stat.isBlockDevice()) === "boolean");
142 assert.ok(typeof(stat.isCharacterDevice()) === "boolean");
143 assert.ok(typeof(stat.isFIFO()) === "boolean");
144 assert.ok(typeof(stat.isSocket()) === "boolean");
145 assert.ok(typeof(stat.hidden) === "boolean");
146 assert.ok(typeof(stat.writable) === "boolean")
147 assert.ok(stat.readable === true);
148
149 end();
150 });
151 async = true;
152 };
153
154 exports["test fs.stat dir"] = function(assert, end) {
155 let async = false;
156 let path = dirPathInProfile;
157 fs.stat(path, function(error, stat) {
158 assert.ok(async, "fs.stat is async");
159 assert.ok(!error, "error is falsy");
160 assert.ok(stat.isDirectory(), "is a dir");
161 assert.ok(!stat.isFile(), "not a file");
162 assert.ok(!stat.isSymbolicLink(), "isn't a symlink");
163 assert.ok(typeof(stat.size) === "number", "size is a number");
164 assert.ok(stat.exists === true, "file exists");
165 assert.ok(typeof(stat.isBlockDevice()) === "boolean");
166 assert.ok(typeof(stat.isCharacterDevice()) === "boolean");
167 assert.ok(typeof(stat.isFIFO()) === "boolean");
168 assert.ok(typeof(stat.isSocket()) === "boolean");
169 assert.ok(typeof(stat.hidden) === "boolean");
170 assert.ok(typeof(stat.writable) === "boolean")
171 assert.ok(typeof(stat.readable) === "boolean");
172
173 end();
174 });
175 async = true;
176 };
177
178 exports["test fs.stat error"] = function(assert, end) {
179 let async = false;
180 let path = filePathInProfile + "-does-not-exists";
181 fs.stat(path, function(error, stat) {
182 assert.ok(async, "fs.stat is async");
183 assert.equal(error.message, "ENOENT, stat " + path);
184 assert.equal(error.code, "ENOENT", "error has a code");
185 assert.equal(error.path, path, "error has a path");
186 assert.equal(error.errno, 34, "error has a errno");
187
188 end();
189 });
190 async = true;
191 };
192
193 exports["test fs.exists NO"] = function(assert, end) {
194 let async = false
195 let path = filePathInProfile + "-does-not-exists";
196 fs.exists(path, function(error, value) {
197 assert.ok(async, "fs.exists is async");
198 assert.ok(!error, "error is falsy");
199 assert.ok(!value, "file does not exists");
200 end();
201 });
202 async = true;
203 };
204
205 exports["test fs.exists YES"] = function(assert, end) {
206 let async = false
207 let path = filePathInProfile
208 fs.exists(path, function(error, value) {
209 assert.ok(async, "fs.exists is async");
210 assert.ok(!error, "error is falsy");
211 assert.ok(value, "file exists");
212 end();
213 });
214 async = true;
215 };
216
217 exports["test fs.exists NO"] = function(assert, end) {
218 let async = false
219 let path = filePathInProfile + "-does-not-exists";
220 fs.exists(path, function(error, value) {
221 assert.ok(async, "fs.exists is async");
222 assert.ok(!error, "error is falsy");
223 assert.ok(!value, "file does not exists");
224 end();
225 });
226 async = true;
227 };
228
229 exports["test fs.existsSync"] = function(assert) {
230 let path = filePathInProfile
231 assert.equal(fs.existsSync(path), true, "exists");
232 assert.equal(fs.existsSync(path + "-does-not-exists"), false, "exists");
233 };
234
235 exports["test fs.mkdirSync fs.rmdirSync"] = function(assert) {
236 let path = mkdirPath;
237
238 assert.equal(fs.existsSync(path), false, "does not exists");
239 fs.mkdirSync(path);
240 assert.equal(fs.existsSync(path), true, "dir was created");
241 try {
242 fs.mkdirSync(path);
243 assert.fail(Error("mkdir on existing should throw"));
244 } catch (error) {
245 assert.equal(error.message, "EEXIST, mkdir " + path);
246 assert.equal(error.code, "EEXIST", "error has a code");
247 assert.equal(error.path, path, "error has a path");
248 assert.equal(error.errno, 47, "error has a errno");
249 }
250 fs.rmdirSync(path);
251 assert.equal(fs.existsSync(path), false, "dir was removed");
252 };
253
254 exports["test fs.mkdir"] = function(assert, end) {
255 let path = mkdirPath;
256
257 if (!fs.existsSync(path)) {
258 let async = false;
259 fs.mkdir(path, function(error) {
260 assert.ok(async, "mkdir is async");
261 assert.ok(!error, "no error");
262 assert.equal(fs.existsSync(path), true, "dir was created");
263 fs.rmdirSync(path);
264 assert.equal(fs.existsSync(path), false, "dir was removed");
265 end();
266 });
267 async = true;
268 }
269 };
270
271 exports["test fs.mkdir error"] = function(assert, end) {
272 let path = mkdirPath;
273
274 if (!fs.existsSync(path)) {
275 fs.mkdirSync(path);
276 let async = false;
277 fs.mkdir(path, function(error) {
278 assert.ok(async, "mkdir is async");
279 assert.equal(error.message, "EEXIST, mkdir " + path);
280 assert.equal(error.code, "EEXIST", "error has a code");
281 assert.equal(error.path, path, "error has a path");
282 assert.equal(error.errno, 47, "error has a errno");
283 fs.rmdirSync(path);
284 assert.equal(fs.existsSync(path), false, "dir was removed");
285 end();
286 });
287 async = true;
288 }
289 };
290
291 exports["test fs.rmdir"] = function(assert, end) {
292 let path = mkdirPath;
293
294 if (!fs.existsSync(path)) {
295 fs.mkdirSync(path);
296 assert.equal(fs.existsSync(path), true, "dir exists");
297 let async = false;
298 fs.rmdir(path, function(error) {
299 assert.ok(async, "mkdir is async");
300 assert.ok(!error, "no error");
301 assert.equal(fs.existsSync(path), false, "dir was removed");
302 end();
303 });
304 async = true;
305 }
306 };
307
308
309 exports["test fs.rmdir error"] = function(assert, end) {
310 let path = mkdirPath;
311
312 if (!fs.existsSync(path)) {
313 assert.equal(fs.existsSync(path), false, "dir doesn't exists");
314 let async = false;
315 fs.rmdir(path, function(error) {
316 assert.ok(async, "mkdir is async");
317 assert.equal(error.message, "ENOENT, remove " + path);
318 assert.equal(error.code, "ENOENT", "error has a code");
319 assert.equal(error.path, path, "error has a path");
320 assert.equal(error.errno, 34, "error has a errno");
321 assert.equal(fs.existsSync(path), false, "dir is removed");
322 end();
323 });
324 async = true;
325 }
326 };
327
328 exports["test fs.truncateSync fs.unlinkSync"] = function(assert) {
329 let path = truncatePath;
330
331 assert.equal(fs.existsSync(path), false, "does not exists");
332 fs.truncateSync(path);
333 assert.equal(fs.existsSync(path), true, "file was created");
334 fs.truncateSync(path);
335 fs.unlinkSync(path);
336 assert.equal(fs.existsSync(path), false, "file was removed");
337 };
338
339
340 exports["test fs.truncate"] = function(assert, end) {
341 let path = truncatePath;
342 if (!fs.existsSync(path)) {
343 let async = false;
344 fs.truncate(path, 0, function(error) {
345 assert.ok(async, "truncate is async");
346 assert.ok(!error, "no error");
347 assert.equal(fs.existsSync(path), true, "file was created");
348 fs.unlinkSync(path);
349 assert.equal(fs.existsSync(path), false, "file was removed");
350 end();
351 })
352 async = true;
353 }
354 };
355
356 exports["test fs.unlink"] = function(assert, end) {
357 let path = unlinkPath;
358 let async = false;
359 assert.ok(!fs.existsSync(path), "file doesn't exists yet");
360 fs.truncateSync(path, 0);
361 assert.ok(fs.existsSync(path), "file was created");
362 fs.unlink(path, function(error) {
363 assert.ok(async, "fs.unlink is async");
364 assert.ok(!error, "error is falsy");
365 assert.ok(!fs.existsSync(path), "file was removed");
366 end();
367 });
368 async = true;
369 };
370
371 exports["test fs.unlink error"] = function(assert, end) {
372 let path = unlinkPath;
373 let async = false;
374 assert.ok(!fs.existsSync(path), "file doesn't exists yet");
375 fs.unlink(path, function(error) {
376 assert.ok(async, "fs.unlink is async");
377 assert.equal(error.message, "ENOENT, remove " + path);
378 assert.equal(error.code, "ENOENT", "error has a code");
379 assert.equal(error.path, path, "error has a path");
380 assert.equal(error.errno, 34, "error has a errno");
381 end();
382 });
383 async = true;
384 };
385
386 exports["test fs.rename"] = function(assert, end) {
387 let fromPath = renameFromPath;
388 let toPath = renameToPath;
389
390 fs.truncateSync(fromPath);
391 assert.ok(fs.existsSync(fromPath), "source file exists");
392 assert.ok(!fs.existsSync(toPath), "destination doesn't exists");
393 var async = false;
394 fs.rename(fromPath, toPath, function(error) {
395 assert.ok(async, "fs.rename is async");
396 assert.ok(!error, "error is falsy");
397 assert.ok(!fs.existsSync(fromPath), "source path no longer exists");
398 assert.ok(fs.existsSync(toPath), "destination file exists");
399 fs.unlinkSync(toPath);
400 assert.ok(!fs.existsSync(toPath), "cleaned up properly");
401 end();
402 });
403 async = true;
404 };
405
406 exports["test fs.rename (missing source file)"] = function(assert, end) {
407 let fromPath = renameFromPath;
408 let toPath = renameToPath;
409
410 assert.ok(!fs.existsSync(fromPath), "source file doesn't exists");
411 assert.ok(!fs.existsSync(toPath), "destination doesn't exists");
412 var async = false;
413 fs.rename(fromPath, toPath, function(error) {
414 assert.ok(async, "fs.rename is async");
415 assert.equal(error.message, "ENOENT, rename " + fromPath);
416 assert.equal(error.code, "ENOENT", "error has a code");
417 assert.equal(error.path, fromPath, "error has a path");
418 assert.equal(error.errno, 34, "error has a errno");
419 end();
420 });
421 async = true;
422 };
423
424 exports["test fs.rename (existing target file)"] = function(assert, end) {
425 let fromPath = renameFromPath;
426 let toPath = renameToPath;
427
428 fs.truncateSync(fromPath);
429 fs.truncateSync(toPath);
430 assert.ok(fs.existsSync(fromPath), "source file exists");
431 assert.ok(fs.existsSync(toPath), "destination file exists");
432 var async = false;
433 fs.rename(fromPath, toPath, function(error) {
434 assert.ok(async, "fs.rename is async");
435 assert.ok(!error, "error is falsy");
436 assert.ok(!fs.existsSync(fromPath), "source path no longer exists");
437 assert.ok(fs.existsSync(toPath), "destination file exists");
438 fs.unlinkSync(toPath);
439 assert.ok(!fs.existsSync(toPath), "cleaned up properly");
440 end();
441 });
442 async = true;
443 };
444
445 exports["test fs.writeFile"] = function(assert, end) {
446 let path = writePath;
447 let content = ["hello world",
448 "this is some text"].join("\n");
449
450 var async = false;
451 fs.writeFile(path, content, function(error) {
452 assert.ok(async, "fs write is async");
453 assert.ok(!error, "error is falsy");
454 assert.ok(fs.existsSync(path), "file was created");
455 assert.equal(fs.readFileSync(path).toString(),
456 content,
457 "contet was written");
458 fs.unlinkSync(path);
459 assert.ok(!fs.exists(path), "file was removed");
460
461 end();
462 });
463 async = true;
464 };
465
466 exports["test fs.writeFile (with large files)"] = function(assert, end) {
467 let path = writePath;
468 let content = "";
469
470 for (var i = 0; i < 100000; i++) {
471 content += "buffer\n";
472 }
473
474 var async = false;
475 fs.writeFile(path, content, function(error) {
476 assert.ok(async, "fs write is async");
477 assert.ok(!error, "error is falsy");
478 assert.ok(fs.existsSync(path), "file was created");
479 assert.equal(fs.readFileSync(path).toString(),
480 content,
481 "contet was written");
482 fs.unlinkSync(path);
483 assert.ok(!fs.exists(path), "file was removed");
484
485 end();
486 });
487 async = true;
488 };
489
490 exports["test fs.writeFile error"] = function (assert, done) {
491 try {
492 fs.writeFile({}, 'content', function (err) {
493 assert.fail('Error thrown from TypeError should not be caught');
494 });
495 } catch (e) {
496 assert.ok(e,
497 'writeFile with a non-string error should not be caught');
498 assert.equal(e.name, 'TypeError', 'error should be TypeError');
499 }
500 fs.writeFile('not/a/valid/path', 'content', function (err) {
501 assert.ok(err, 'error caught and handled in callback');
502 done();
503 });
504 };
505
506 exports["test fs.chmod"] = function (assert, done) {
507 let content = ["hej från sverige"];
508
509 fs.writeFile(chmodPath, content, function (err) {
510 testPerm("0755")()
511 .then(testPerm("0777"))
512 .then(testPerm("0666"))
513 .then(testPerm(parseInt("0511", 8)))
514 .then(testPerm(parseInt("0200", 8)))
515 .then(testPerm("0040"))
516 .then(testPerm("0000"))
517 .then(testPermSync(parseInt("0777", 8)))
518 .then(testPermSync(parseInt("0666", 8)))
519 .then(testPermSync("0511"))
520 .then(testPermSync("0200"))
521 .then(testPermSync("0040"))
522 .then(testPermSync("0000"))
523 .then(() => {
524 assert.pass("Successful chmod passes");
525 }, assert.fail)
526 // Test invalid paths
527 .then(() => chmod("not-a-valid-file", parseInt("0755", 8)))
528 .then(assert.fail, (err) => {
529 checkPermError(err, "not-a-valid-file");
530 })
531 .then(() => chmod("not-a-valid-file", parseInt("0755", 8), "sync"))
532 .then(assert.fail, (err) => {
533 checkPermError(err, "not-a-valid-file");
534 })
535 // Test invalid files
536 .then(() => chmod("resource://not-a-real-file", parseInt("0755", 8)))
537 .then(assert.fail, (err) => {
538 checkPermError(err, "resource://not-a-real-file");
539 })
540 .then(() => chmod("resource://not-a-real-file", parseInt("0755", 8), 'sync'))
541 .then(assert.fail, (err) => {
542 checkPermError(err, "resource://not-a-real-file");
543 })
544 .then(done, assert.fail);
545 });
546
547 function checkPermError (err, path) {
548 assert.equal(err.message, "ENOENT, chmod " + path);
549 assert.equal(err.code, "ENOENT", "error has a code");
550 assert.equal(err.path, path, "error has a path");
551 assert.equal(err.errno, 34, "error has a errno");
552 }
553
554 function chmod (path, mode, sync) {
555 let { promise, resolve, reject } = defer();
556 if (!sync) {
557 fs.chmod(path, mode, (err) => {
558 if (err) reject(err);
559 else resolve();
560 });
561 } else {
562 fs.chmodSync(path, mode);
563 resolve();
564 }
565 return promise;
566 }
567
568 function testPerm (mode, sync) {
569 return function () {
570 return chmod(chmodPath, mode, sync)
571 .then(() => getPerm(chmodPath))
572 .then(perm => {
573 let nMode = normalizeMode(mode);
574 if (isWindows)
575 assert.equal(perm, nMode,
576 "mode correctly set to " + mode + " (" + nMode + " on windows)");
577 else
578 assert.equal(perm, nMode, "mode correctly set to " + nMode);
579 });
580 };
581 }
582
583 function testPermSync (mode) {
584 return testPerm(mode, true);
585 }
586
587 function getPerm (path) {
588 let { promise, resolve, reject } = defer();
589 fs.stat(path, function (err, stat) {
590 if (err) reject(err);
591 else resolve(stat.mode);
592 });
593 return promise;
594 }
595
596 /*
597 * Converts a unix mode `0755` into a Windows version of unix permissions
598 */
599 function normalizeMode (mode) {
600 if (typeof mode === "string")
601 mode = parseInt(mode, 8);
602
603 if (!isWindows)
604 return mode;
605
606 var ANY_READ = parseInt("0444", 8);
607 var ANY_WRITE = parseInt("0222", 8);
608 var winMode = 0;
609
610 // On Windows, if WRITE is true, then READ is also true
611 if (mode & ANY_WRITE)
612 winMode |= ANY_WRITE | ANY_READ;
613 // Minimum permissions are READ for Windows
614 else
615 winMode |= ANY_READ;
616
617 return winMode;
618 }
619 };
620
621 require("test").run(exports);

mercurial