javaunit-testingniojimfs

Testing file system interaction: Setting file permissions


I stumbled upon Jimfs and wanted to use it for testing methods with file system interaction. For example, I wrote a pretty long method that figures out, if writing to a list of files could succeed:

static boolean exportable(List<Path> paths, boolean force) {
    List<Path> created = new LinkedList<>();
    boolean success = true;
    for (Path p : paths) {
        if (Files.exists(p)) {
            if (Files.isDirectory(p)) {
                success = false;
                log.error("Can't export results to file '{}': It's a directory!", p);
            } else if (force) {
                if (!Files.isWritable(p)) {
                    success = false;
                    log.error("Can't export to file '{}': No write access!", p);
                }
            } else {
                success = false;
                log.error("Can't export to file '{}': File does already exist and overwrite (-f) is not enabled!",
                        p);
            }
        } else { // does not exist
            Path parent = p.toAbsolutePath().normalize().getParent();
            if (Files.exists(parent)) {
                try {
                    Files.createFile(p);
                    created.add(p);
                    log.debug("Created file '{}'", p);
                } catch (AccessDeniedException e) {
                    success = false;
                    log.error("Can't export to file '{}': File could not be created. Access denied!", p);
                } catch (IOException e) {
                    success = false;
                    log.error("Can't export to file '{}': File could not be created!", p, e);
                }
            } else if (force) {
                List<Path> createdDirs = new ArrayList<>();
                try {
                    createParentDirectories(parent, createdDirs);
                } catch (IOException e) {
                    success = false;
                    log.error("Can't export to file '{}': Failed to create all parent directories!", p, e);
                }
                created.addAll(createdDirs);
                try {
                    Files.createFile(p);
                    created.add(p);
                    log.debug("Created file '{}'.", p);
                } catch (IOException e) {
                    success = false;
                    log.error("Can't export to file '{}': File could not be created!", p, e);
                }
            } else {
                success = false;
                log.error("Can't export to file '{}': File could not be created, because the parent directory '{}'"
                        + " does not exist and automatic parent directory creation (-f) is not enabled!", p, parent);
            }
        }
    }
    if (!success && created.size() > 0) {
        log.debug("Beginning to delete files and directories created while checking exportability.");
        Collections.reverse(created); // delete created folders in reverse order
        for (Path p : created) {
            try {
                Files.delete(p);
                log.debug("Successfully deleted '{}'.", p);
            } catch (IOException e) {
                log.warn("Deleting file '{}' failed, which was created during exportability check!", p, e);
            }
        }
        log.debug("Finished cleaning up created files and directories.");
    }
}

What I want to do now is to write tests like this one:

public void testExportToExistingFile_forceButNotWritable() throws Exception {
    FileSystem fs = Jimfs.newFileSystem();
    Path file = fs.getPath("file");
    Files.createFile(file);
    // How to deny writing to 'file' here???
    assertFalse(exportable(ImmutableList.of(file), true));
}

Can I use Jimfs to do this? If not, how would you test this method?


Solution

  • Unfortunately, Jimfs currently doesn't support any kind of permission checking. It's definitely something that might be nice to have in the future, it's just somewhat complicated (by the differences in how permissions are set between POSIX and Windows file systems, for example) and didn't seem necessary for most use cases.