// 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.unix;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for the {@link NativePosixFiles} class. */
@RunWith(JUnit4.class)
public class NativePosixFilesTest {
  private FileSystem testFS;
  private Path workingDir;
  private Path testFile;

  @Before
  public final void createFileSystem() throws Exception  {
    testFS = new UnixFileSystem(DigestHashFunction.getDefaultUnchecked());
    workingDir = testFS.getPath(new File(TestUtils.tmpDir()).getCanonicalPath());
    testFile = workingDir.getRelative("test");
  }

  @Test
  public void throwsFileNotFoundException() throws Exception {
    FileNotFoundException e =
        assertThrows(
            FileNotFoundException.class, () -> NativePosixFiles.stat(testFile.getPathString()));
    assertThat(e).hasMessageThat().isEqualTo(testFile + " (No such file or directory)");
  }

  @Test
  public void throwsFilePermissionException() throws Exception {
    File foo = new File("/bin");
    try {
      NativePosixFiles.chmod(
          foo.getPath(),
          NativePosixFiles.lstat(foo.getPath()).getPermissions() | FileStatus.S_IWUSR);
      fail("Expected FilePermissionException or IOException, but wasn't thrown.");
    } catch (FilePermissionException e) {
      assertThat(e).hasMessageThat().isEqualTo(foo + " (Operation not permitted)");
    } catch (IOException e) {
      // When running in a sandbox, /bin might actually be a read-only file system.
      assertThat(e).hasMessageThat().isEqualTo(foo + " (Read-only file system)");
    }
  }

  /** Skips the test if the file system does not support extended attributes. */
  private static void assumeXattrsSupported() throws Exception {
    // The standard file systems on macOS support extended attributes by default, so we can assume
    // that the test will work on that platform. For other systems, we currently don't have a
    // mechanism to validate this so the tests are skipped unconditionally.
    assumeTrue(OS.getCurrent() == OS.DARWIN);
  }

  @Test
  public void testGetxattr_AttributeFound() throws Exception {
    assumeXattrsSupported();

    String myfile = Files.createTempFile("getxattrtest", null).toString();
    Runtime.getRuntime().exec("xattr -w foo bar " + myfile).waitFor();

    assertThat(new String(NativePosixFiles.getxattr(myfile, "foo"), UTF_8)).isEqualTo("bar");
    assertThat(new String(NativePosixFiles.lgetxattr(myfile, "foo"), UTF_8)).isEqualTo("bar");
  }

  @Test
  public void testGetxattr_AttributeNotFoundReturnsNull() throws Exception {
    assumeXattrsSupported();

    String myfile = Files.createTempFile("getxattrtest", null).toString();

    assertThat(NativePosixFiles.getxattr(myfile, "foo")).isNull();
    assertThat(NativePosixFiles.lgetxattr(myfile, "foo")).isNull();
  }

  @Test
  public void testGetxattr_FileNotFound() throws Exception {
    String nonexistentFile = workingDir.getChild("nonexistent").toString();

    assertThrows(
        FileNotFoundException.class, () -> NativePosixFiles.getxattr(nonexistentFile, "foo"));
    assertThrows(
        FileNotFoundException.class, () -> NativePosixFiles.lgetxattr(nonexistentFile, "foo"));
  }

  @Test
  public void writing() throws Exception {
    java.nio.file.Path myfile = Files.createTempFile("myfile", null);
    int fd1 = NativePosixFiles.openWrite(myfile.toString(), false);
    assertThrows(
        IndexOutOfBoundsException.class,
        () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 5, 1));
    assertThrows(
        IndexOutOfBoundsException.class,
        () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, -1, 1));
    assertThrows(
        IndexOutOfBoundsException.class,
        () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 0, -1));
    assertThrows(
        IndexOutOfBoundsException.class,
        () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 0, 5));
    NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 0, 4);
    NativePosixFiles.close(fd1, null);
    assertThat(Files.readAllBytes(myfile)).isEqualTo(new byte[] {0, 1, 2, 3});
    // Try appending.
    int fd2 = NativePosixFiles.openWrite(myfile.toString(), true);
    NativePosixFiles.write(fd2, new byte[] {5, 6, 7, 8, 9}, 1, 3);
    NativePosixFiles.close(fd2, null);
    assertThat(Files.readAllBytes(myfile)).isEqualTo(new byte[] {0, 1, 2, 3, 6, 7, 8});
  }
}
