// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.vfs;

import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.google.common.io.BaseEncoding;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.unix.NativePosixFiles;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.Preconditions;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.FileAlreadyExistsException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * This class handles the generic tests that any filesystem must pass.
 *
 * <p>Each filesystem-test should inherit from this class, thereby obtaining
 * all the tests.
 */
public abstract class FileSystemTest {

  private long savedTime;
  protected FileSystem testFS;
  protected boolean supportsSymlinks;
  protected boolean supportsHardlinks;
  protected Path workingDir;

  // Some useful examples of various kinds of files (mnemonic: "x" = "eXample")
  protected Path xNothing;
  protected Path xLink;
  protected Path xFile;
  protected Path xNonEmptyDirectory;
  protected Path xNonEmptyDirectoryFoo;
  protected Path xEmptyDirectory;

  @Before
  public final void createDirectories() throws Exception  {
    executeBeforeCreatingDirectories();
    testFS = getFreshFileSystem();
    workingDir = testFS.getPath(getTestTmpDir());
    cleanUpWorkingDirectory(workingDir);
    supportsSymlinks = testFS.supportsSymbolicLinksNatively();
    supportsHardlinks = testFS.supportsHardLinksNatively();

    // % ls -lR
    // -rw-rw-r-- xFile
    // drwxrwxr-x xNonEmptyDirectory
    // -rw-rw-r-- xNonEmptyDirectory/foo
    // drwxrwxr-x xEmptyDirectory

    xNothing = absolutize("xNothing");
    xLink = absolutize("xLink");
    xFile = absolutize("xFile");
    xNonEmptyDirectory = absolutize("xNonEmptyDirectory");
    xNonEmptyDirectoryFoo = xNonEmptyDirectory.getChild("foo");
    xEmptyDirectory = absolutize("xEmptyDirectory");

    FileSystemUtils.createEmptyFile(xFile);
    xNonEmptyDirectory.createDirectory();
    FileSystemUtils.createEmptyFile(xNonEmptyDirectoryFoo);
    xEmptyDirectory.createDirectory();
  }

  protected void executeBeforeCreatingDirectories() throws Exception {
    // This method exists because LazyDigestFileSystemTest requires some code to be run before
    // createDirectories().
  }

  @After
  public final void destroyFileSystem() throws Exception  {
    destroyFileSystem(testFS);
  }

  /**
   * Returns an instance of the file system to test.
   */
  protected abstract FileSystem getFreshFileSystem() throws IOException;

  protected boolean isSymbolicLink(File file) {
    return NativePosixFiles.isSymbolicLink(file);
  }

  protected void setWritable(File file) throws IOException {
    NativePosixFiles.setWritable(file);
  }

  protected void setExecutable(File file) throws IOException {
    NativePosixFiles.setExecutable(file);
  }

  private static final Pattern STAT_SUBDIR_ERROR = Pattern.compile("(.*) \\(Not a directory\\)");

  // Test that file is not present, using statIfFound. Base implementation throws an exception, but
  // subclasses may override statIfFound to return null, in which case their tests should override
  // this method.
  @SuppressWarnings("unused") // Subclasses may throw.
  protected void expectNotFound(Path path) throws IOException {
    try {
      assertNull(path.statIfFound());
    } catch (IOException e) {
      // May be because of a non-directory path component. Parse exception to check this.
      Matcher matcher = STAT_SUBDIR_ERROR.matcher(e.getMessage());
      if (!matcher.matches() || !path.getPathString().startsWith(matcher.group(1))) {
        // Throw if this doesn't match what an ENOTDIR error looks like.
        throw e;
      }
    }
  }

  /**
   * Removes all stuff from the test filesystem.
   */
  protected void destroyFileSystem(FileSystem fileSystem) throws IOException {
    Preconditions.checkArgument(fileSystem.equals(workingDir.getFileSystem()));
    cleanUpWorkingDirectory(workingDir);
  }

  /**
   * Cleans up the working directory by removing everything.
   */
  protected void cleanUpWorkingDirectory(Path workingPath)
      throws IOException {
    if (workingPath.exists()) {
      removeEntireDirectory(workingPath.getPathFile()); // uses java.io.File!
    }
    FileSystemUtils.createDirectoryAndParents(workingPath);
  }

  /**
   * This function removes an entire directory and all of its contents.
   * Much like rm -rf directoryToRemove
   */
  protected void removeEntireDirectory(File directoryToRemove)
      throws IOException {
    // make sure that we do not remove anything outside the test directory
    Path testDirPath = testFS.getPath(getTestTmpDir());
    if (!testFS.getPath(directoryToRemove.getAbsolutePath()).startsWith(testDirPath)) {
      throw new IOException("trying to remove files outside of the testdata directory");
    }
    // Some tests set the directories read-only and/or non-executable, so
    // override that:
    setWritable(directoryToRemove);
    setExecutable(directoryToRemove);

    File[] files = directoryToRemove.listFiles();
    if (files != null) {
      for (File currentFile : files) {
        boolean isSymbolicLink = isSymbolicLink(currentFile);
        if (!isSymbolicLink && currentFile.isDirectory()) {
          removeEntireDirectory(currentFile);
        } else {
          if (!isSymbolicLink) {
            setWritable(currentFile);
          }
          if (!currentFile.delete()) {
            throw new IOException("Failed to delete '" + currentFile + "'");
          }
        }
      }
    }
    if (!directoryToRemove.delete()) {
      throw new IOException("Failed to delete '" + directoryToRemove + "'");
    }
  }

  /**
   * Returns the directory to use as the FileSystem's working directory.
   * Canonicalized to make tests hermetic against symbolic links in TEST_TMPDIR.
   */
  protected final String getTestTmpDir() throws IOException {
    return new File(TestUtils.tmpDir()).getCanonicalPath() + "/testdir";
  }

  /**
   * Indirection to create links so we can test FileSystems that do not support
   * link creation.  For example, JavaFileSystemTest overrides this method
   * and creates the link with an alternate FileSystem.
   */
  protected void createSymbolicLink(Path link, Path target) throws IOException {
    createSymbolicLink(link, target.asFragment());
  }

  /**
   * Indirection to create links so we can test FileSystems that do not support
   * link creation.  For example, JavaFileSystemTest overrides this method
   * and creates the link with an alternate FileSystem.
   */
  protected void createSymbolicLink(Path link, PathFragment target) throws IOException {
    link.createSymbolicLink(target);
  }

  /**
   * Indirection to setReadOnly(false) on FileSystems that do not
   * support setReadOnly(false).  For example, JavaFileSystemTest overrides this
   * method and makes the Path writable with an alternate FileSystem.
   */
  protected void makeWritable(Path target) throws IOException {
    target.setWritable(true);
  }

  /**
   * Indirection to {@link Path#setExecutable(boolean)} on FileSystems that do
   * not support setExecutable.  For example, JavaFileSystemTest overrides this
   * method and makes the Path executable with an alternate FileSystem.
   */
  protected void setExecutable(Path target, boolean mode) throws IOException {
    target.setExecutable(mode);
  }

  // TODO(bazel-team): (2011) Put in a setLastModifiedTime into the various objects
  // and clobber the current time of the object we're currently handling.
  // Otherwise testing the thing might get a little hard, depending on the clock.
  void storeReferenceTime(long timeToMark) {
    savedTime = timeToMark;
  }

  boolean isLaterThanreferenceTime(long testTime) {
    return (savedTime <= testTime);
  }

  protected Path absolutize(String relativePathName) {
    return workingDir.getRelative(relativePathName);
  }

  // Here the tests begin.

  @Test
  public void testIsFileForNonexistingPath() {
    Path nonExistingPath = testFS.getPath("/something/strange");
    assertFalse(nonExistingPath.isFile());
  }

  @Test
  public void testIsDirectoryForNonexistingPath() {
    Path nonExistingPath = testFS.getPath("/something/strange");
    assertFalse(nonExistingPath.isDirectory());
  }

  @Test
  public void testIsLinkForNonexistingPath() {
    Path nonExistingPath = testFS.getPath("/something/strange");
    assertFalse(nonExistingPath.isSymbolicLink());
  }

  @Test
  public void testExistsForNonexistingPath() throws Exception {
    Path nonExistingPath = testFS.getPath("/something/strange");
    assertFalse(nonExistingPath.exists());
    expectNotFound(nonExistingPath);
  }

  @Test
  public void testBadPermissionsThrowsExceptionOnStatIfFound() throws Exception {
    Path inaccessible = absolutize("inaccessible");
    inaccessible.createDirectory();
    Path child = inaccessible.getChild("child");
    FileSystemUtils.createEmptyFile(child);
    inaccessible.setExecutable(false);
    assertFalse(child.exists());
    try {
      child.statIfFound();
      fail();
    } catch (IOException expected) {
      // Expected.
    }
  }

  @Test
  public void testStatIfFoundReturnsNullForChildOfNonDir() throws Exception {
    Path foo = absolutize("foo");
    foo.createDirectory();
    Path nonDir = foo.getRelative("bar");
    FileSystemUtils.createEmptyFile(nonDir);
    assertNull(nonDir.getRelative("file").statIfFound());
  }

  // The following tests check the handling of the current working directory.
  @Test
  public void testCreatePathRelativeToWorkingDirectory() {
    Path relativeCreatedPath = absolutize("some-file");
    Path expectedResult = workingDir.getRelative(new PathFragment("some-file"));

    assertEquals(expectedResult, relativeCreatedPath);
  }

  // The following tests check the handling of the root directory
  @Test
  public void testRootIsDirectory() {
    Path rootPath = testFS.getPath("/");
    assertTrue(rootPath.isDirectory());
  }

  @Test
  public void testRootHasNoParent() {
    Path rootPath = testFS.getPath("/");
    assertNull(rootPath.getParentDirectory());
  }

  // The following functions test the creation of files/links/directories.
  @Test
  public void testFileExists() throws Exception {
    Path someFile = absolutize("some-file");
    FileSystemUtils.createEmptyFile(someFile);
    assertTrue(someFile.exists());
    assertNotNull(someFile.statIfFound());
  }

  @Test
  public void testFileIsFile() throws Exception {
    Path someFile = absolutize("some-file");
    FileSystemUtils.createEmptyFile(someFile);
    assertTrue(someFile.isFile());
  }

  @Test
  public void testFileIsNotDirectory() throws Exception {
    Path someFile = absolutize("some-file");
    FileSystemUtils.createEmptyFile(someFile);
    assertFalse(someFile.isDirectory());
  }

  @Test
  public void testFileIsNotSymbolicLink() throws Exception {
    Path someFile = absolutize("some-file");
    FileSystemUtils.createEmptyFile(someFile);
    assertFalse(someFile.isSymbolicLink());
  }

  @Test
  public void testDirectoryExists() throws Exception {
    Path someDirectory = absolutize("some-dir");
    someDirectory.createDirectory();
    assertTrue(someDirectory.exists());
    assertNotNull(someDirectory.statIfFound());
  }

  @Test
  public void testDirectoryIsDirectory() throws Exception {
    Path someDirectory = absolutize("some-dir");
    someDirectory.createDirectory();
    assertTrue(someDirectory.isDirectory());
  }

  @Test
  public void testDirectoryIsNotFile() throws Exception {
    Path someDirectory = absolutize("some-dir");
    someDirectory.createDirectory();
    assertFalse(someDirectory.isFile());
  }

  @Test
  public void testDirectoryIsNotSymbolicLink() throws Exception {
    Path someDirectory = absolutize("some-dir");
    someDirectory.createDirectory();
    assertFalse(someDirectory.isSymbolicLink());
  }

  @Test
  public void testSymbolicFileLinkExists() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xFile);
      assertTrue(someLink.exists());
      assertNotNull(someLink.statIfFound());
    }
  }

  @Test
  public void testSymbolicFileLinkIsSymbolicLink() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xFile);
      assertTrue(someLink.isSymbolicLink());
    }
  }

  @Test
  public void testSymbolicFileLinkIsFile() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xFile);
      assertTrue(someLink.isFile());
    }
  }

  @Test
  public void testSymbolicFileLinkIsNotDirectory() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xFile);
      assertFalse(someLink.isDirectory());
    }
  }

  @Test
  public void testSymbolicDirLinkExists() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xEmptyDirectory);
      assertTrue(someLink.exists());
      assertNotNull(someLink.statIfFound());
    }
  }

  @Test
  public void testSymbolicDirLinkIsSymbolicLink() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xEmptyDirectory);
      assertTrue(someLink.isSymbolicLink());
    }
  }

  @Test
  public void testSymbolicDirLinkIsDirectory() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xEmptyDirectory);
      assertTrue(someLink.isDirectory());
    }
  }

  @Test
  public void testSymbolicDirLinkIsNotFile() throws Exception {
    if (supportsSymlinks) {
      Path someLink = absolutize("some-link");
      someLink.createSymbolicLink(xEmptyDirectory);
      assertFalse(someLink.isFile());
    }
  }

  @Test
  public void testChildOfNonDirectory() throws Exception {
    Path somePath = absolutize("file-name");
    FileSystemUtils.createEmptyFile(somePath);
    Path childOfNonDir = somePath.getChild("child");
    assertFalse(childOfNonDir.exists());
    expectNotFound(childOfNonDir);
  }

  @Test
  public void testCreateDirectoryIsEmpty() throws Exception {
    Path newPath = xEmptyDirectory.getChild("new-dir");
    newPath.createDirectory();
    assertEquals(newPath.getDirectoryEntries().size(), 0);
  }

  @Test
  public void testCreateDirectoryIsOnlyChildInParent() throws Exception {
    Path newPath = xEmptyDirectory.getChild("new-dir");
    newPath.createDirectory();
    assertThat(newPath.getParentDirectory().getDirectoryEntries()).hasSize(1);
    assertThat(newPath.getParentDirectory().getDirectoryEntries()).containsExactly(newPath);
  }

  @Test
  public void testCreateDirectories() throws Exception {
    Path newPath = absolutize("new-dir/sub/directory");
    assertTrue(FileSystemUtils.createDirectoryAndParents(newPath));
  }

  @Test
  public void testCreateDirectoriesIsDirectory() throws Exception {
    Path newPath = absolutize("new-dir/sub/directory");
    FileSystemUtils.createDirectoryAndParents(newPath);
    assertTrue(newPath.isDirectory());
  }

  @Test
  public void testCreateDirectoriesIsNotFile() throws Exception {
    Path newPath = absolutize("new-dir/sub/directory");
    FileSystemUtils.createDirectoryAndParents(newPath);
    assertFalse(newPath.isFile());
  }

  @Test
  public void testCreateDirectoriesIsNotSymbolicLink() throws Exception {
    Path newPath = absolutize("new-dir/sub/directory");
    FileSystemUtils.createDirectoryAndParents(newPath);
    assertFalse(newPath.isSymbolicLink());
  }

  @Test
  public void testCreateDirectoriesIsEmpty() throws Exception {
    Path newPath = absolutize("new-dir/sub/directory");
    FileSystemUtils.createDirectoryAndParents(newPath);
    assertEquals(newPath.getDirectoryEntries().size(), 0);
  }

  @Test
  public void testCreateDirectoriesIsOnlyChildInParent() throws Exception {
    Path newPath = absolutize("new-dir/sub/directory");
    FileSystemUtils.createDirectoryAndParents(newPath);
    assertThat(newPath.getParentDirectory().getDirectoryEntries()).hasSize(1);
    assertThat(newPath.getParentDirectory().getDirectoryEntries()).containsExactly(newPath);
  }

  @Test
  public void testCreateEmptyFileIsEmpty() throws Exception {
    Path newPath = xEmptyDirectory.getChild("new-file");
    FileSystemUtils.createEmptyFile(newPath);

    assertEquals(newPath.getFileSize(), 0);
  }

  @Test
  public void testCreateFileIsOnlyChildInParent() throws Exception {
    Path newPath = xEmptyDirectory.getChild("new-file");
    FileSystemUtils.createEmptyFile(newPath);
    assertThat(newPath.getParentDirectory().getDirectoryEntries()).hasSize(1);
    assertThat(newPath.getParentDirectory().getDirectoryEntries()).containsExactly(newPath);
  }

  // The following functions test the behavior if errors occur during the
  // creation of files/links/directories.
  @Test
  public void testCreateDirectoryWhereDirectoryAlreadyExists() throws Exception {
    assertFalse(xEmptyDirectory.createDirectory());
  }

  @Test
  public void testCreateDirectoryWhereFileAlreadyExists() {
    try {
      xFile.createDirectory();
      fail();
    } catch (IOException e) {
      assertThat(e).hasMessage(xFile + " (File exists)");
    }
  }

  @Test
  public void testCannotCreateDirectoryWithoutExistingParent() throws Exception {
    Path newPath = testFS.getPath("/deep/new-dir");
    try {
      newPath.createDirectory();
      fail();
    } catch (FileNotFoundException e) {
      assertThat(e.getMessage()).endsWith(" (No such file or directory)");
    }
  }

  @Test
  public void testCannotCreateDirectoryWithReadOnlyParent() throws Exception {
    xEmptyDirectory.setWritable(false);
    Path xChildOfReadonlyDir = xEmptyDirectory.getChild("x");
    try {
      xChildOfReadonlyDir.createDirectory();
      fail();
    } catch (IOException e) {
      assertThat(e).hasMessage(xChildOfReadonlyDir + " (Permission denied)");
    }
  }

  @Test
  public void testCannotCreateFileWithoutExistingParent() throws Exception {
    Path newPath = testFS.getPath("/non-existing-dir/new-file");
    try {
      FileSystemUtils.createEmptyFile(newPath);
      fail();
    } catch (FileNotFoundException e) {
      assertThat(e.getMessage()).endsWith(" (No such file or directory)");
    }
  }

  @Test
  public void testCannotCreateFileWithReadOnlyParent() throws Exception {
    xEmptyDirectory.setWritable(false);
    Path xChildOfReadonlyDir = xEmptyDirectory.getChild("x");
    try {
      FileSystemUtils.createEmptyFile(xChildOfReadonlyDir);
      fail();
    } catch (IOException e) {
      assertThat(e).hasMessage(xChildOfReadonlyDir + " (Permission denied)");
    }
  }

  @Test
  public void testCannotCreateFileWithinFile() throws Exception {
    Path newFilePath = absolutize("some-file");
    FileSystemUtils.createEmptyFile(newFilePath);
    Path wrongPath = absolutize("some-file/new-file");
    try {
      FileSystemUtils.createEmptyFile(wrongPath);
      fail();
    } catch (IOException e) {
      assertThat(e.getMessage()).endsWith(" (Not a directory)");
    }
  }

  @Test
  public void testCannotCreateDirectoryWithinFile() throws Exception {
    Path newFilePath = absolutize("some-file");
    FileSystemUtils.createEmptyFile(newFilePath);
    Path wrongPath = absolutize("some-file/new-file");
    try {
      wrongPath.createDirectory();
      fail();
    } catch (IOException e) {
      assertThat(e.getMessage()).endsWith(" (Not a directory)");
    }
  }

  // Test directory contents
  @Test
  public void testCreateMultipleChildren() throws Exception {
    Path theDirectory = absolutize("foo/");
    theDirectory.createDirectory();
    Path newPath1 = absolutize("foo/new-file-1");
    Path newPath2 = absolutize("foo/new-file-2");
    Path newPath3 = absolutize("foo/new-file-3");

    FileSystemUtils.createEmptyFile(newPath1);
    FileSystemUtils.createEmptyFile(newPath2);
    FileSystemUtils.createEmptyFile(newPath3);

    assertThat(theDirectory.getDirectoryEntries()).containsExactly(newPath1, newPath2, newPath3);
  }

  @Test
  public void testGetDirectoryEntriesThrowsExceptionWhenRunOnFile() throws Exception {
    try {
      xFile.getDirectoryEntries();
      fail("No Exception thrown.");
    } catch (IOException ex) {
      if (ex instanceof FileNotFoundException) {
        fail("The method should throw an object of class IOException.");
      }
      assertThat(ex).hasMessage(xFile + " (Not a directory)");
    }
  }

  @Test
  public void testGetDirectoryEntriesThrowsExceptionForNonexistingPath() {
    Path somePath = testFS.getPath("/non-existing-path");
    try {
      somePath.getDirectoryEntries();
      fail("FileNotFoundException not thrown.");
    } catch (Exception x) {
      assertThat(x).hasMessage(somePath + " (No such file or directory)");
    }
  }

  // Test the removal of items
  @Test
  public void testDeleteDirectory() throws Exception {
    assertTrue(xEmptyDirectory.delete());
  }

  @Test
  public void testDeleteDirectoryIsNotDirectory() throws Exception {
    xEmptyDirectory.delete();
    assertFalse(xEmptyDirectory.isDirectory());
  }

  @Test
  public void testDeleteDirectoryParentSize() throws Exception {
    int parentSize = workingDir.getDirectoryEntries().size();
    xEmptyDirectory.delete();
    assertEquals(workingDir.getDirectoryEntries().size(), parentSize - 1);
  }

  @Test
  public void testDeleteFile() throws Exception {
    assertTrue(xFile.delete());
  }

  @Test
  public void testDeleteFileIsNotFile() throws Exception {
    xFile.delete();
    assertFalse(xEmptyDirectory.isFile());
  }

  @Test
  public void testDeleteFileParentSize() throws Exception {
    int parentSize = workingDir.getDirectoryEntries().size();
    xFile.delete();
    assertEquals(workingDir.getDirectoryEntries().size(), parentSize - 1);
  }

  @Test
  public void testDeleteRemovesCorrectFile() throws Exception {
    Path newPath1 = xEmptyDirectory.getChild("new-file-1");
    Path newPath2 = xEmptyDirectory.getChild("new-file-2");
    Path newPath3 = xEmptyDirectory.getChild("new-file-3");

    FileSystemUtils.createEmptyFile(newPath1);
    FileSystemUtils.createEmptyFile(newPath2);
    FileSystemUtils.createEmptyFile(newPath3);

    assertTrue(newPath2.delete());
    assertThat(xEmptyDirectory.getDirectoryEntries()).containsExactly(newPath1, newPath3);
  }

  @Test
  public void testDeleteNonExistingDir() throws Exception {
    Path path = xEmptyDirectory.getRelative("non-existing-dir");
    assertFalse(path.delete());
  }

  @Test
  public void testDeleteNotADirectoryPath() throws Exception {
    Path path = xFile.getChild("new-file");
    assertFalse(path.delete());
  }

  // Here we test the situations where delete should throw exceptions.
  @Test
  public void testDeleteNonEmptyDirectoryThrowsException() throws Exception {
    try {
      xNonEmptyDirectory.delete();
      fail();
    } catch (IOException e) {
      assertThat(e).hasMessage(xNonEmptyDirectory + " (Directory not empty)");
    }
  }

  @Test
  public void testDeleteNonEmptyDirectoryNotDeletedDirectory() throws Exception {
    try {
      xNonEmptyDirectory.delete();
      fail();
    } catch (IOException e) {
      // Expected
    }

    assertTrue(xNonEmptyDirectory.isDirectory());
  }

  @Test
  public void testDeleteNonEmptyDirectoryNotDeletedFile() throws Exception {
    try {
      xNonEmptyDirectory.delete();
      fail();
    } catch (IOException e) {
      // Expected
    }

    assertTrue(xNonEmptyDirectoryFoo.isFile());
  }

  @Test
  public void testCannotRemoveRoot() {
    Path rootDirectory = testFS.getRootDirectory();
    try {
      rootDirectory.delete();
      fail();
    } catch (IOException e) {
      String msg = e.getMessage();
      assertTrue(String.format("got %s want EBUSY or ENOTEMPTY", msg),
          msg.endsWith(" (Directory not empty)")
          || msg.endsWith(" (Device or resource busy)")
          || msg.endsWith(" (Is a directory)"));  // Happens on OS X.
    }
  }

  // Test the date functions
  @Test
  public void testCreateFileChangesTimeOfDirectory() throws Exception {
    storeReferenceTime(workingDir.getLastModifiedTime());
    Path newPath = absolutize("new-file");
    FileSystemUtils.createEmptyFile(newPath);
    assertTrue(isLaterThanreferenceTime(workingDir.getLastModifiedTime()));
  }

  @Test
  public void testRemoveFileChangesTimeOfDirectory() throws Exception {
    Path newPath = absolutize("new-file");
    FileSystemUtils.createEmptyFile(newPath);
    storeReferenceTime(workingDir.getLastModifiedTime());
    newPath.delete();
    assertTrue(isLaterThanreferenceTime(workingDir.getLastModifiedTime()));
  }

  // This test is a little bit strange, as we cannot test the progression
  // of the time directly. As the Java time and the OS time are slightly different.
  // Therefore, we first create an unrelated file to get a notion
  // of the current OS time and use that as a baseline.
  @Test
  public void testCreateFileTimestamp() throws Exception {
    Path syncFile = absolutize("sync-file");
    FileSystemUtils.createEmptyFile(syncFile);

    Path newFile = absolutize("new-file");
    storeReferenceTime(syncFile.getLastModifiedTime());
    FileSystemUtils.createEmptyFile(newFile);
    assertTrue(isLaterThanreferenceTime(newFile.getLastModifiedTime()));
  }

  @Test
  public void testCreateDirectoryTimestamp() throws Exception {
    Path syncFile = absolutize("sync-file");
    FileSystemUtils.createEmptyFile(syncFile);

    Path newPath = absolutize("new-dir");
    storeReferenceTime(syncFile.getLastModifiedTime());
    assertTrue(newPath.createDirectory());
    assertTrue(isLaterThanreferenceTime(newPath.getLastModifiedTime()));
  }

  @Test
  public void testWriteChangesModifiedTime() throws Exception {
    storeReferenceTime(xFile.getLastModifiedTime());
    FileSystemUtils.writeContentAsLatin1(xFile, "abc19");
    assertTrue(isLaterThanreferenceTime(xFile.getLastModifiedTime()));
  }

  @Test
  public void testGetLastModifiedTimeThrowsExceptionForNonexistingPath() throws Exception {
    Path newPath = testFS.getPath("/non-existing-dir");
    try {
      newPath.getLastModifiedTime();
      fail("FileNotFoundException not thrown!");
    } catch (FileNotFoundException x) {
      assertThat(x).hasMessage(newPath + " (No such file or directory)");
    }
  }

  // Test file size
  @Test
  public void testFileSizeThrowsExceptionForNonexistingPath() throws Exception {
    Path newPath = testFS.getPath("/non-existing-file");
    try {
      newPath.getFileSize();
      fail("FileNotFoundException not thrown.");
    } catch (FileNotFoundException e) {
      assertThat(e).hasMessage(newPath + " (No such file or directory)");
    }
  }

  @Test
  public void testFileSizeAfterWrite() throws Exception {
    String testData = "abc19";

    FileSystemUtils.writeContentAsLatin1(xFile, testData);
    assertEquals(testData.length(), xFile.getFileSize());
  }

  // Testing the input/output routines
  @Test
  public void testFileWriteAndReadAsLatin1() throws Exception {
    String testData = "abc19";

    FileSystemUtils.writeContentAsLatin1(xFile, testData);
    String resultData = new String(FileSystemUtils.readContentAsLatin1(xFile));

    assertEquals(testData,resultData);
  }

  @Test
  public void testInputAndOutputStreamEOF() throws Exception {
    try (OutputStream outStream = xFile.getOutputStream()) {
      outStream.write(1);
    }

    try (InputStream inStream = xFile.getInputStream()) {
      inStream.read();
    assertEquals(-1, inStream.read());
    }
  }

  @Test
  public void testInputAndOutputStream() throws Exception {
    try (OutputStream outStream = xFile.getOutputStream()) {
      for (int i = 33; i < 126; i++) {
        outStream.write(i);
      }
    }

    try (InputStream inStream = xFile.getInputStream()) {
      for (int i = 33; i < 126; i++) {
        int readValue = inStream.read();
        assertEquals(i, readValue);
      }
    }
  }

  @Test
  public void testInputAndOutputStreamAppend() throws Exception {
    try (OutputStream outStream = xFile.getOutputStream()) {
      for (int i = 33; i < 126; i++) {
        outStream.write(i);
      }
    }

    try (OutputStream appendOut = xFile.getOutputStream(true)) {
      for (int i = 126; i < 155; i++) {
        appendOut.write(i);
      }
    }

    try (InputStream inStream = xFile.getInputStream()) {
      for (int i = 33; i < 155; i++) {
        int readValue = inStream.read();
        assertEquals(i, readValue);
      }
    }
  }

  @Test
  public void testInputAndOutputStreamNoAppend() throws Exception {
    try (OutputStream outStream = xFile.getOutputStream()) {
      outStream.write(1);
    }

    try (OutputStream noAppendOut = xFile.getOutputStream(false)) {
    }

    try (InputStream inStream = xFile.getInputStream()) {
      assertEquals(-1, inStream.read());
    }
  }

  @Test
  public void testGetOutputStreamCreatesFile() throws Exception {
    Path newFile = absolutize("does_not_exist_yet.txt");

    try (OutputStream out = newFile.getOutputStream()) {
      out.write(42);
    }

    assertTrue(newFile.isFile());
  }

  @Test
  public void testOutputStreamThrowExceptionOnDirectory() throws Exception {
    try {
      xEmptyDirectory.getOutputStream();
      fail("The Exception was not thrown!");
    } catch (IOException ex) {
      assertThat(ex).hasMessage(xEmptyDirectory + " (Is a directory)");
    }
  }

  @Test
  public void testInputStreamThrowExceptionOnDirectory() throws Exception {
    try {
      xEmptyDirectory.getInputStream();
      fail("The Exception was not thrown!");
    } catch (IOException ex) {
      assertThat(ex).hasMessage(xEmptyDirectory + " (Is a directory)");
    }
  }

  // Test renaming
  @Test
  public void testCanRenameToUnusedName() throws Exception {
    xFile.renameTo(xNothing);
    assertFalse(xFile.exists());
    assertTrue(xNothing.isFile());
  }

  @Test
  public void testCanRenameFileToExistingFile() throws Exception {
    Path otherFile = absolutize("otherFile");
    FileSystemUtils.createEmptyFile(otherFile);
    xFile.renameTo(otherFile); // succeeds
    assertFalse(xFile.exists());
    assertTrue(otherFile.isFile());
  }

  @Test
  public void testCanRenameDirToExistingEmptyDir() throws Exception {
    xNonEmptyDirectory.renameTo(xEmptyDirectory); // succeeds
    assertFalse(xNonEmptyDirectory.exists());
    assertTrue(xEmptyDirectory.isDirectory());
    assertThat(xEmptyDirectory.getDirectoryEntries()).isNotEmpty();
  }

  @Test
  public void testCantRenameDirToExistingNonEmptyDir() throws Exception {
    try {
      xEmptyDirectory.renameTo(xNonEmptyDirectory);
      fail();
    } catch (IOException e) {
      assertThat(e.getMessage()).endsWith(" (Directory not empty)");
    }
  }

  @Test
  public void testCantRenameDirToExistingNonEmptyDirNothingChanged() throws Exception {
    try {
      xEmptyDirectory.renameTo(xNonEmptyDirectory);
      fail();
    } catch (IOException e) {
      // Expected
    }

    assertTrue(xNonEmptyDirectory.isDirectory());
    assertTrue(xEmptyDirectory.isDirectory());
    assertThat(xEmptyDirectory.getDirectoryEntries()).isEmpty();
    assertThat(xNonEmptyDirectory.getDirectoryEntries()).isNotEmpty();
  }

  @Test
  public void testCantRenameDirToExistingFile() {
    try {
      xEmptyDirectory.renameTo(xFile);
      fail();
    } catch (IOException e) {
      assertThat(e).hasMessage(xEmptyDirectory + " -> " + xFile + " (Not a directory)");
    }
  }

  @Test
  public void testCantRenameDirToExistingFileNothingChanged() {
    try {
      xEmptyDirectory.renameTo(xFile);
      fail();
    } catch (IOException e) {
      // Expected
    }

    assertTrue(xEmptyDirectory.isDirectory());
    assertTrue(xFile.isFile());
  }

  @Test
  public void testCantRenameFileToExistingDir() {
    try {
      xFile.renameTo(xEmptyDirectory);
      fail();
    } catch (IOException e) {
      assertThat(e).hasMessage(xFile + " -> " + xEmptyDirectory + " (Is a directory)");
    }
  }

  @Test
  public void testCantRenameFileToExistingDirNothingChanged() {
    try {
      xFile.renameTo(xEmptyDirectory);
      fail();
    } catch (IOException e) {
      // Expected
    }

    assertTrue(xEmptyDirectory.isDirectory());
    assertTrue(xFile.isFile());
  }

  @Test
  public void testMoveOnNonExistingFileThrowsException() throws Exception {
    Path nonExistingPath = absolutize("non-existing");
    Path targetPath = absolutize("does-not-matter");
    try {
      nonExistingPath.renameTo(targetPath);
      fail();
    } catch (FileNotFoundException e) {
      assertThat(e.getMessage()).endsWith(" (No such file or directory)");
    }
  }

  // Test the Paths
  @Test
  public void testGetPathOnlyAcceptsAbsolutePath() {
    try {
      testFS.getPath("not-absolute");
      fail("The expected Exception was not thrown.");
    } catch (IllegalArgumentException ex) {
      assertThat(ex).hasMessage("not-absolute (not an absolute path)");
    }
  }

  @Test
  public void testGetPathOnlyAcceptsAbsolutePathFragment() {
    try {
      testFS.getPath(new PathFragment("not-absolute"));
      fail("The expected Exception was not thrown.");
    } catch (IllegalArgumentException ex) {
      assertThat(ex).hasMessage("not-absolute (not an absolute path)");
    }
  }

  // Test the access permissions
  @Test
  public void testNewFilesAreWritable() throws Exception {
    assertTrue(xFile.isWritable());
  }

  @Test
  public void testNewFilesAreReadable() throws Exception {
    assertTrue(xFile.isReadable());
  }

  @Test
  public void testNewDirsAreWritable() throws Exception {
    assertTrue(xEmptyDirectory.isWritable());
  }

  @Test
  public void testNewDirsAreReadable() throws Exception {
    assertTrue(xEmptyDirectory.isReadable());
  }

  @Test
  public void testNewDirsAreExecutable() throws Exception {
    assertTrue(xEmptyDirectory.isExecutable());
  }

  @Test
  public void testCannotGetExecutableOnNonexistingFile() throws Exception {
    try {
      xNothing.isExecutable();
      fail("No exception thrown.");
    } catch (FileNotFoundException ex) {
      assertThat(ex).hasMessage(xNothing + " (No such file or directory)");
    }
  }

  @Test
  public void testCannotSetExecutableOnNonexistingFile() throws Exception {
    try {
      xNothing.setExecutable(true);
      fail("No exception thrown.");
    } catch (FileNotFoundException ex) {
      assertThat(ex).hasMessage(xNothing + " (No such file or directory)");
    }
  }

  @Test
  public void testCannotGetWritableOnNonexistingFile() throws Exception {
    try {
      xNothing.isWritable();
      fail("No exception thrown.");
    } catch (FileNotFoundException ex) {
      assertThat(ex).hasMessage(xNothing + " (No such file or directory)");
    }
  }

  @Test
  public void testCannotSetWritableOnNonexistingFile() throws Exception {
    try {
      xNothing.setWritable(false);
      fail("No exception thrown.");
    } catch (FileNotFoundException ex) {
      assertThat(ex).hasMessage(xNothing + " (No such file or directory)");
    }
  }

  @Test
  public void testSetReadableOnFile() throws Exception {
    xFile.setReadable(false);
    assertFalse(xFile.isReadable());
    xFile.setReadable(true);
    assertTrue(xFile.isReadable());
  }

  @Test
  public void testSetWritableOnFile() throws Exception {
    xFile.setWritable(false);
    assertFalse(xFile.isWritable());
    xFile.setWritable(true);
    assertTrue(xFile.isWritable());
  }

  @Test
  public void testSetExecutableOnFile() throws Exception {
    xFile.setExecutable(true);
    assertTrue(xFile.isExecutable());
    xFile.setExecutable(false);
    assertFalse(xFile.isExecutable());
  }

  @Test
  public void testSetExecutableOnDirectory() throws Exception {
    setExecutable(xNonEmptyDirectory, false);

    try {
      // We can't map names->inodes in a non-executable directory:
      xNonEmptyDirectoryFoo.isWritable(); // i.e. stat
      fail();
    } catch (IOException e) {
      assertThat(e.getMessage()).endsWith(" (Permission denied)");
    }
  }

  @Test
  public void testWritingToReadOnlyFileThrowsException() throws Exception {
    xFile.setWritable(false);
    try {
      FileSystemUtils.writeContent(xFile, "hello, world!".getBytes(UTF_8));
      fail("No exception thrown.");
    } catch (IOException e) {
      assertThat(e).hasMessage(xFile + " (Permission denied)");
    }
  }

  @Test
  public void testReadingFromUnreadableFileThrowsException() throws Exception {
    FileSystemUtils.writeContent(xFile, "hello, world!".getBytes(UTF_8));
    xFile.setReadable(false);
    try {
      FileSystemUtils.readContent(xFile);
      fail("No exception thrown.");
    } catch (IOException e) {
      assertThat(e).hasMessage(xFile + " (Permission denied)");
    }
  }

  @Test
  public void testCannotCreateFileInReadOnlyDirectory() throws Exception {
    Path xNonEmptyDirectoryBar = xNonEmptyDirectory.getChild("bar");
    xNonEmptyDirectory.setWritable(false);

    try {
      FileSystemUtils.createEmptyFile(xNonEmptyDirectoryBar);
      fail("No exception thrown.");
    } catch (IOException e) {
      assertThat(e).hasMessage(xNonEmptyDirectoryBar + " (Permission denied)");
    }
  }

  @Test
  public void testCannotCreateDirectoryInReadOnlyDirectory() throws Exception {
    Path xNonEmptyDirectoryBar = xNonEmptyDirectory.getChild("bar");
    xNonEmptyDirectory.setWritable(false);

    try {
      xNonEmptyDirectoryBar.createDirectory();
      fail("No exception thrown.");
    } catch (IOException e) {
      assertThat(e).hasMessage(xNonEmptyDirectoryBar + " (Permission denied)");
    }
  }

  @Test
  public void testCannotMoveIntoReadOnlyDirectory() throws Exception {
    Path xNonEmptyDirectoryBar = xNonEmptyDirectory.getChild("bar");
    xNonEmptyDirectory.setWritable(false);

    try {
      xFile.renameTo(xNonEmptyDirectoryBar);
      fail("No exception thrown.");
    } catch (IOException e) {
      assertThat(e.getMessage()).endsWith(" (Permission denied)");
    }
  }

  @Test
  public void testCannotMoveFromReadOnlyDirectory() throws Exception {
    xNonEmptyDirectory.setWritable(false);

    try {
      xNonEmptyDirectoryFoo.renameTo(xNothing);
      fail("No exception thrown.");
    } catch (IOException e) {
      assertThat(e.getMessage()).endsWith(" (Permission denied)");
    }
  }

  @Test
  public void testCannotDeleteInReadOnlyDirectory() throws Exception {
    xNonEmptyDirectory.setWritable(false);

    try {
      xNonEmptyDirectoryFoo.delete();
      fail("No exception thrown.");
    } catch (IOException e) {
      assertThat(e).hasMessage(xNonEmptyDirectoryFoo + " (Permission denied)");
    }
  }

  @Test
  public void testCannotCreatSymbolicLinkInReadOnlyDirectory() throws Exception {
    Path xNonEmptyDirectoryBar = xNonEmptyDirectory.getChild("bar");
    xNonEmptyDirectory.setWritable(false);

    if (supportsSymlinks) {
      try {
        createSymbolicLink(xNonEmptyDirectoryBar, xNonEmptyDirectoryFoo);
        fail("No exception thrown.");
      } catch (IOException e) {
        assertThat(e).hasMessage(xNonEmptyDirectoryBar + " (Permission denied)");
      }
    }
  }

  @Test
  public void testGetMD5DigestForEmptyFile() throws Exception {
    Fingerprint fp = new Fingerprint();
    fp.addBytes(new byte[0]);
    assertEquals(BaseEncoding.base16().lowerCase().encode(xFile.getMD5Digest()),
        fp.hexDigestAndReset());
  }

  @Test
  public void testGetMD5Digest() throws Exception {
    byte[] buffer = new byte[500000];
    for (int i = 0; i < buffer.length; ++i) {
      buffer[i] = 1;
    }
    FileSystemUtils.writeContent(xFile, buffer);
    Fingerprint fp = new Fingerprint();
    fp.addBytes(buffer);
    assertEquals(BaseEncoding.base16().lowerCase().encode(xFile.getMD5Digest()),
        fp.hexDigestAndReset());
  }

  @Test
  public void testStatFailsFastOnNonExistingFiles() throws Exception {
    try {
      xNothing.stat();
      fail("Expected IOException");
    } catch(IOException e) {
      // Do nothing.
    }
  }

  @Test
  public void testStatNullableFailsFastOnNonExistingFiles() throws Exception {
    assertNull(xNothing.statNullable());
  }

  @Test
  public void testResolveSymlinks() throws Exception {
    if (supportsSymlinks) {
      createSymbolicLink(xLink, xFile);
      FileSystemUtils.createEmptyFile(xFile);
      assertEquals(xFile.asFragment(), testFS.resolveOneLink(xLink));
      assertEquals(xFile, xLink.resolveSymbolicLinks());
    }
  }

  @Test
  public void testResolveDanglingSymlinks() throws Exception {
    if (supportsSymlinks) {
      createSymbolicLink(xLink, xNothing);
      assertEquals(xNothing.asFragment(), testFS.resolveOneLink(xLink));
      try {
        xLink.resolveSymbolicLinks();
        fail();
      } catch (IOException expected) {
      }
    }
  }

  @Test
  public void testResolveNonSymlinks() throws Exception {
    if (supportsSymlinks) {
      assertNull(testFS.resolveOneLink(xFile));
      assertEquals(xFile, xFile.resolveSymbolicLinks());
    }
  }

  @Test
  public void testCreateHardLink_Success() throws Exception {
    if (!supportsHardlinks) {
      return;
    }
    xFile.createHardLink(xLink);
    assertTrue(xFile.exists());
    assertTrue(xLink.exists());
    assertTrue(xFile.isFile());
    assertTrue(xLink.isFile());
    assertTrue(isHardLinked(xFile, xLink));
  }

  @Test
  public void testCreateHardLink_NeitherOriginalNorLinkExists() throws Exception {
    if (!supportsHardlinks) {
      return;
    }

    /* Neither original file nor link file exists */
    xFile.delete();
    try {
      xFile.createHardLink(xLink);
      fail("expected FileNotFoundException: File \"xFile\" linked from \"xLink\" does not exist");
    } catch (FileNotFoundException expected) {
      assertThat(expected).hasMessage("File \"xFile\" linked from \"xLink\" does not exist");
    }
    assertFalse(xFile.exists());
    assertFalse(xLink.exists());
  }

  @Test
  public void testCreateHardLink_OriginalDoesNotExistAndLinkExists() throws Exception {

    if (!supportsHardlinks) {
      return;
    }

    /* link file exists and original file does not exist */
    xFile.delete();
    FileSystemUtils.createEmptyFile(xLink);

    try {
      xFile.createHardLink(xLink);
      fail("expected FileNotFoundException: File \"xFile\" linked from \"xLink\" does not exist");
    } catch (FileNotFoundException expected) {
      assertThat(expected).hasMessage("File \"xFile\" linked from \"xLink\" does not exist");
    }
    assertFalse(xFile.exists());
    assertTrue(xLink.exists());
  }

  @Test
  public void testCreateHardLink_BothOriginalAndLinkExist() throws Exception {

    if (!supportsHardlinks) {
      return;
    }
    /* Both original file and link file exist */
    FileSystemUtils.createEmptyFile(xLink);

    try {
      xFile.createHardLink(xLink);
      fail("expected FileAlreadyExistsException: New link file \"xLink\" already exists");
    } catch (FileAlreadyExistsException expected) {
      assertThat(expected).hasMessage("New link file \"xLink\" already exists");
    }
    assertTrue(xFile.exists());
    assertTrue(xLink.exists());
    assertFalse(isHardLinked(xFile, xLink));
  }

  protected boolean isHardLinked(Path a, Path b) throws IOException {
    return testFS.stat(a, false).getNodeId() == testFS.stat(b, false).getNodeId();
  }
}
