// 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 com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;

import com.google.common.collect.Lists;
import com.google.common.testing.EqualsTester;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.vfs.util.FileSystems;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link Path} in combination with the native file system for the current platform. */
@RunWith(JUnit4.class)
public class NativePathTest {

  private FileSystem fs;
  private File aDirectory;
  private File aFile;
  private File anotherFile;
  private File tmpDir;

  protected FileSystem getNativeFileSystem() {
    return FileSystems.getNativeFileSystem();
  }

  @Before
  public final void createFiles() throws Exception  {
    fs = getNativeFileSystem();
    tmpDir = new File(TestUtils.tmpDir(), "tmpDir");
    tmpDir.mkdirs();
    aDirectory = new File(tmpDir, "a_directory");
    aDirectory.mkdirs();
    aFile = new File(tmpDir, "a_file");
    new FileOutputStream(aFile).close();
    anotherFile = new File(aDirectory, "another_file.txt");
    new FileOutputStream(anotherFile).close();
  }

  @Test
  public void testExists() {
    assertThat(fs.getPath(aDirectory.getPath()).exists()).isTrue();
    assertThat(fs.getPath(aFile.getPath()).exists()).isTrue();
    assertThat(fs.getPath("/does/not/exist").exists()).isFalse();
  }

  @Test
  public void testDirectoryEntriesForDirectory() throws IOException {
    assertThat(fs.getPath(tmpDir.getPath()).getDirectoryEntries()).containsExactly(
      fs.getPath(tmpDir.getPath() + "/a_file"),
      fs.getPath(tmpDir.getPath() + "/a_directory"));

  }

  @Test
  public void testDirectoryEntriesForFileThrowsException() {
    assertThrows(IOException.class, () -> fs.getPath(aFile.getPath()).getDirectoryEntries());
  }

  @Test
  public void testIsFileIsTrueForFile() {
    assertThat(fs.getPath(aFile.getPath()).isFile()).isTrue();
  }

  @Test
  public void testIsFileIsFalseForDirectory() {
    assertThat(fs.getPath(aDirectory.getPath()).isFile()).isFalse();
  }

  @Test
  public void testBaseName() {
    assertThat(fs.getPath("/foo/base").getBaseName()).isEqualTo("base");
  }

  @Test
  public void testBaseNameRunsAfterDotDotInterpretation() {
    assertThat(fs.getPath("/base/foo/..").getBaseName()).isEqualTo("base");
  }

  @Test
  public void testIsDirectory() {
    assertThat(fs.getPath(aDirectory.getPath()).isDirectory()).isTrue();
    assertThat(fs.getPath(aFile.getPath()).isDirectory()).isFalse();
    assertThat(fs.getPath("/does/not/exist").isDirectory()).isFalse();
  }

  @Test
  public void testListNonExistingDirectoryThrowsException() {
    assertThrows(IOException.class, () -> fs.getPath("/does/not/exist").getDirectoryEntries());
  }

  private void assertPathSet(Collection<Path> actual, String... expected) {
    List<String> actualStrings = Lists.newArrayListWithCapacity(actual.size());

    for (Path path : actual) {
      actualStrings.add(path.getPathString());
    }

    assertThat(actualStrings).containsExactlyElementsIn(Arrays.asList(expected));
  }

  @Test
  public void testGlob() throws Exception {
    Collection<Path> textFiles = UnixGlob.forPath(fs.getPath(tmpDir.getPath()))
        .addPattern("*/*.txt")
        .globInterruptible();
    assertThat(textFiles).hasSize(1);
    Path onlyFile = textFiles.iterator().next();
    assertThat(onlyFile).isEqualTo(fs.getPath(anotherFile.getPath()));

    Collection<Path> onlyFiles =
        UnixGlob.forPath(fs.getPath(tmpDir.getPath()))
        .addPattern("*")
        .setExcludeDirectories(true)
        .globInterruptible();
    assertPathSet(onlyFiles, aFile.getPath());

    Collection<Path> directoriesToo =
        UnixGlob.forPath(fs.getPath(tmpDir.getPath()))
        .addPattern("*")
        .setExcludeDirectories(false)
        .globInterruptible();
    assertPathSet(directoriesToo, aFile.getPath(), aDirectory.getPath());
  }

  @Test
  public void testGetRelative() {
    Path relative = fs.getPath("/foo").getChild("bar");
    Path expected = fs.getPath("/foo/bar");
    assertThat(relative).isEqualTo(expected);
  }

  @Test
  public void testEqualsAndHash() {
    Path path = fs.getPath("/foo/bar");
    Path equalPath = fs.getPath("/foo/bar");
    Path differentPath = fs.getPath("/foo/bar/baz");
    Object differentType = new Object();

    new EqualsTester().addEqualityGroup(path, equalPath).testEquals();
    assertThat(path.equals(differentPath)).isFalse();
    assertThat(path.equals(differentType)).isFalse();
  }

  @Test
  public void testLatin1ReadAndWrite() throws IOException {
    char[] allLatin1Chars = new char[256];
    for (int i = 0; i < 256; i++) {
      allLatin1Chars[i] = (char) i;
    }
    Path path = fs.getPath(aFile.getPath());
    String latin1String = new String(allLatin1Chars);
    FileSystemUtils.writeContentAsLatin1(path, latin1String);
    String fileContent = new String(FileSystemUtils.readContentAsLatin1(path));
    assertThat(latin1String).isEqualTo(fileContent);
  }

  /**
   * Verify that the encoding implemented by {@link
   * com.google.devtools.build.lib.vfs.FileSystemUtils#writeContentAsLatin1(Path, String)} really is
   * 8859-1 (latin1).
   */
  @Test
  public void testVerifyLatin1() throws IOException {
    char[] allLatin1Chars = new char[256];
    for( int i = 0; i < 256; i++) {
      allLatin1Chars[i] = (char)i;
    }
    Path path = fs.getPath(aFile.getPath());
    String latin1String = new String(allLatin1Chars);
    FileSystemUtils.writeContentAsLatin1(path, latin1String);
    byte[] bytes = FileSystemUtils.readContent(path);
    assertThat(latin1String).isEqualTo(new String(bytes, "ISO-8859-1"));
  }

  @Test
  public void testBytesReadAndWrite() throws IOException {
    byte[] bytes = new byte[] { (byte) 0xdeadbeef, (byte) 0xdeadbeef>>8,
                                (byte) 0xdeadbeef>>16, (byte) 0xdeadbeef>>24 };
    Path path = fs.getPath(aFile.getPath());
    FileSystemUtils.writeContent(path, bytes);
    byte[] content = FileSystemUtils.readContent(path);
    assertThat(content).hasLength(bytes.length);
    for (int i = 0; i < bytes.length; i++) {
      assertThat(content[i]).isEqualTo(bytes[i]);
    }
  }

  @Test
  public void testInputOutputStreams() throws IOException {
    Path path = fs.getPath(aFile.getPath());
    try (OutputStream out = path.getOutputStream()) {
      for (int i = 0; i < 256; i++) {
        out.write(i);
      }
    }
    try (InputStream in = path.getInputStream()) {
      for (int i = 0; i < 256; i++) {
        assertThat(in.read()).isEqualTo(i);
      }
      assertThat(in.read()).isEqualTo(-1);
    }
  }
}
