michael@0: const CWD = do_get_cwd(); michael@0: function checkOS(os) { michael@0: const nsILocalFile_ = "nsILocalFile" + os; michael@0: return nsILocalFile_ in Components.interfaces && michael@0: CWD instanceof Components.interfaces[nsILocalFile_]; michael@0: } michael@0: michael@0: const DIR_TARGET = "target"; michael@0: const DIR_LINK = "link"; michael@0: const DIR_LINK_LINK = "link_link"; michael@0: const FILE_TARGET = "target.txt"; michael@0: const FILE_LINK = "link.txt"; michael@0: const FILE_LINK_LINK = "link_link.txt"; michael@0: michael@0: const DOES_NOT_EXIST = "doesnotexist"; michael@0: const DANGLING_LINK = "dangling_link"; michael@0: const LOOP_LINK = "loop_link"; michael@0: michael@0: const isWin = checkOS("Win"); michael@0: const isMac = checkOS("Mac"); michael@0: const isUnix = !(isWin || isMac); michael@0: michael@0: const nsIFile = Components.interfaces.nsIFile; michael@0: michael@0: var process; michael@0: function createSymLink(from, to) { michael@0: if (!process) { michael@0: var ln = Components.classes["@mozilla.org/file/local;1"] michael@0: .createInstance(Components.interfaces.nsILocalFile); michael@0: ln.initWithPath("/bin/ln"); michael@0: michael@0: process = Components.classes["@mozilla.org/process/util;1"] michael@0: .createInstance(Components.interfaces.nsIProcess); michael@0: process.init(ln); michael@0: } michael@0: michael@0: const args = ["-s", from, to]; michael@0: process.run(true, args, args.length); michael@0: do_check_eq(process.exitValue, 0); michael@0: } michael@0: michael@0: function makeSymLink(from, toName, relative) { michael@0: var to = from.parent; michael@0: to.append(toName); michael@0: michael@0: if (relative) { michael@0: createSymLink(from.leafName, to.path); michael@0: } michael@0: else { michael@0: createSymLink(from.path, to.path); michael@0: } michael@0: michael@0: do_check_true(to.isSymlink()); michael@0: michael@0: print("---"); michael@0: print(from.path); michael@0: print(to.path); michael@0: print(to.target); michael@0: michael@0: if (from.leafName != DOES_NOT_EXIST && from.isSymlink()) { michael@0: // XXXjag wish I could set followLinks to false so we'd just get michael@0: // the symlink's direct target instead of the final target. michael@0: do_check_eq(from.target, to.target); michael@0: } michael@0: else { michael@0: do_check_eq(from.path, to.target); michael@0: } michael@0: michael@0: return to; michael@0: } michael@0: michael@0: function setupTestDir(testDir, relative) { michael@0: var targetDir = testDir.clone(); michael@0: targetDir.append(DIR_TARGET); michael@0: michael@0: if (testDir.exists()) { michael@0: testDir.remove(true); michael@0: } michael@0: do_check_true(!testDir.exists()); michael@0: michael@0: testDir.create(nsIFile.DIRECTORY_TYPE, 0777); michael@0: michael@0: targetDir.create(nsIFile.DIRECTORY_TYPE, 0777); michael@0: michael@0: var targetFile = testDir.clone(); michael@0: targetFile.append(FILE_TARGET); michael@0: targetFile.create(nsIFile.NORMAL_FILE_TYPE, 0666); michael@0: michael@0: var imaginary = testDir.clone(); michael@0: imaginary.append(DOES_NOT_EXIST); michael@0: michael@0: var loop = testDir.clone(); michael@0: loop.append(LOOP_LINK); michael@0: michael@0: var dirLink = makeSymLink(targetDir, DIR_LINK, relative); michael@0: var fileLink = makeSymLink(targetFile, FILE_LINK, relative); michael@0: michael@0: makeSymLink(dirLink, DIR_LINK_LINK, relative); michael@0: makeSymLink(fileLink, FILE_LINK_LINK, relative); michael@0: michael@0: makeSymLink(imaginary, DANGLING_LINK, relative); michael@0: michael@0: try { michael@0: makeSymLink(loop, LOOP_LINK, relative); michael@0: do_check_true(false); michael@0: } michael@0: catch (e) { michael@0: } michael@0: } michael@0: michael@0: function createSpaces(dirs, files, links) { michael@0: function longest(a, b) a.length > b.length ? a : b; michael@0: return dirs.concat(files, links).reduce(longest, "").replace(/./g, " "); michael@0: } michael@0: michael@0: function testSymLinks(testDir, relative) { michael@0: setupTestDir(testDir, relative); michael@0: michael@0: const dirLinks = [DIR_LINK, DIR_LINK_LINK]; michael@0: const fileLinks = [FILE_LINK, FILE_LINK_LINK]; michael@0: const otherLinks = [DANGLING_LINK, LOOP_LINK]; michael@0: const dirs = [DIR_TARGET].concat(dirLinks); michael@0: const files = [FILE_TARGET].concat(fileLinks); michael@0: const links = otherLinks.concat(dirLinks, fileLinks); michael@0: michael@0: const spaces = createSpaces(dirs, files, links); michael@0: const bools = {false: " false", true: " true "}; michael@0: print(spaces + " dir file symlink"); michael@0: var dirEntries = testDir.directoryEntries; michael@0: while (dirEntries.hasMoreElements()) { michael@0: const file = dirEntries.getNext().QueryInterface(nsIFile); michael@0: const name = file.leafName; michael@0: print(name + spaces.substring(name.length) + bools[file.isDirectory()] + michael@0: bools[file.isFile()] + bools[file.isSymlink()]); michael@0: do_check_eq(file.isDirectory(), dirs.indexOf(name) != -1); michael@0: do_check_eq(file.isFile(), files.indexOf(name) != -1); michael@0: do_check_eq(file.isSymlink(), links.indexOf(name) != -1); michael@0: } michael@0: } michael@0: michael@0: function run_test() { michael@0: // Skip this test on Windows michael@0: if (isWin) michael@0: return; michael@0: michael@0: var testDir = CWD; michael@0: testDir.append("test_symlinks"); michael@0: michael@0: testSymLinks(testDir, false); michael@0: testSymLinks(testDir, true); michael@0: }