// Copyright 2015 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.pkgcache;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryContentInfo;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;

/** TargetPatternEvaluator tests that require a custom filesystem. */
@RunWith(TestParameterInjector.class)
public class TargetPatternEvaluatorIOTest extends AbstractTargetPatternEvaluatorTest {
  private static class Transformer {
    @SuppressWarnings("unused")
    @Nullable
    public FileStatus stat(FileStatus stat, PathFragment path, boolean followSymlinks)
        throws IOException {
      return stat;
    }

    @SuppressWarnings("unused")
    @Nullable
    public Collection<Dirent> readdir(
        Collection<Dirent> readdir, PathFragment path, boolean followSymlinks) throws IOException {
      return readdir;
    }
  }

  private Transformer transformer = new Transformer();

  @Override
  protected FileSystem createFileSystem() {
    return new InMemoryFileSystem(DigestHashFunction.SHA256) {
      @Override
      public FileStatus stat(PathFragment path, boolean followSymlinks) throws IOException {
        FileStatus defaultResult = super.stat(path, followSymlinks);
        return transformer.stat(defaultResult, path, followSymlinks);
      }

      @Nullable
      @Override
      public FileStatus statIfFound(PathFragment path, boolean followSymlinks) {
        return statNullable(path, followSymlinks);
      }

      @Nullable
      @Override
      public FileStatus statNullable(PathFragment path, boolean followSymlinks) {
        FileStatus defaultResult = super.statNullable(path, followSymlinks);
        try {
          return transformer.stat(defaultResult, path, followSymlinks);
        } catch (IOException e) {
          return null;
        }
      }

      @Override
      protected Collection<Dirent> readdir(PathFragment path, boolean followSymlinks)
          throws IOException {
        Collection<Dirent> defaultResult = super.readdir(path, followSymlinks);
        return transformer.readdir(defaultResult, path, followSymlinks);
      }
    };
  }

  /**
   * Tests that a child with an inconsistent stat (first a directory, then not) is handled properly.
   * Even keep-going mode aborts eagerly in the face of inconsistent stats.
   */
  @Test
  public void testBadStat(@TestParameter boolean keepGoing) throws Exception {
    reporter.removeHandler(failFastHandler);
    // Given a package, "parent",
    Path parent = scratch.file("parent/BUILD", "sh_library(name = 'parent')").getParentDirectory();
    // And a child, "badstat",
    parent.getRelative("badstat").createDirectoryAndParents();

    // Such that badstat first reports that it is a directory, and then reports that it isn't,
    this.transformer = createInconsistentFileStateTransformer("parent/badstat");

    TargetParsingException e =
        assertThrows(
            TargetParsingException.class,
            () ->
                parseTargetPatternList(
                    parser, reporter, ImmutableList.of("//parent/..."), keepGoing));
    assertThat(e).hasMessageThat().contains("Inconsistent filesystem operations");
    assertThat(e.getDetailedExitCode().getFailureDetail().getPackageLoading().getCode())
        .isEqualTo(FailureDetails.PackageLoading.Code.TRANSIENT_INCONSISTENT_FILESYSTEM_ERROR);
  }

  /**
   * Tests that a child with an inconsistent stat (first a directory, then not) is handled properly
   * when given a path-as-target. Even keep-going mode aborts eagerly in the face of inconsistent
   * stats.
   */
  @Test
  public void testBadStatPathAsTarget(@TestParameter boolean keepGoing) throws Exception {
    reporter.removeHandler(failFastHandler);
    scratch.file("parent/BUILD", "sh_library(name = 'parent')").getParentDirectory();
    AtomicBoolean returnNull = new AtomicBoolean(false);
    this.transformer =
        new Transformer() {
          @Nullable
          @Override
          public FileStatus stat(FileStatus stat, PathFragment path, boolean followSymlinks) {
            if (path.endsWith(PathFragment.create("parent/BUILD")) && returnNull.getAndSet(true)) {
              return null;
            }
            return stat;
          }
        };

    TargetParsingException e =
        assertThrows(
            TargetParsingException.class,
            () -> parseTargetPatternList(parser, reporter, ImmutableList.of("parent"), keepGoing));
    assertThat(e).hasMessageThat().contains("Inconsistent filesystem operations");
    assertThat(e.getDetailedExitCode().getFailureDetail().getPackageLoading().getCode())
        .isEqualTo(FailureDetails.PackageLoading.Code.TRANSIENT_INCONSISTENT_FILESYSTEM_ERROR);
  }

  /**
   * Tests that a package subdirectory that throws an IOException when it is listed via readdir does
   * not prevent evaluation of the remaining packages beneath a directory and the return of a
   * partial result.
   */
  @Test
  public void testBadReaddirKeepGoing() throws Exception {
    reporter.removeHandler(failFastHandler);
    // Given a package, "parent",
    Path parent = scratch.file("parent/BUILD", "sh_library(name = 'parent')").getParentDirectory();
    // And a child, "badstat",
    parent.getRelative("badstat").createDirectoryAndParents();

    // Such that badstat reports that it is a directory, but throws an error when its Dirents are
    // collected,
    this.transformer = createBadDirectoryListingTransformer("parent/badstat");

    // When we find all the targets beneath parent in keep_going mode, we get the valid target
    // parent:parent, even though processing badstat threw an IOException,
    assertThat(parseListKeepGoing("//parent/...").getFirst())
        .containsExactlyElementsIn(labels("//parent:parent"));

    // And the TargetPatternEvaluator reported the expected ERROR event to the handler.
    assertContainsEvent(
        "Failed to list directory contents, for parent/badstat, skipping: Path ended in "
            + "parent/badstat, so readdir failed",
        ImmutableSet.of(EventKind.ERROR));
  }

  private Transformer createInconsistentFileStateTransformer(final String badPathSuffix) {
    final AtomicBoolean isDirectory = new AtomicBoolean(true);
    return new Transformer() {
      @Nullable
      @Override
      public FileStatus stat(final FileStatus stat, PathFragment path, boolean followSymlinks) {
        if (path.getPathString().endsWith(badPathSuffix)) {
          return new InMemoryContentInfo(BlazeClock.instance()) {
            @Override
            public boolean isDirectory() {
              // Trigger inconsistent filesystem exception.
              return isDirectory.getAndSet(false);
            }

            @Override
            public boolean isFile() {
              return stat.isFile();
            }

            @Override
            public boolean isSpecialFile() {
              return stat.isSpecialFile();
            }

            @Override
            public boolean isSymbolicLink() {
              return stat.isSymbolicLink();
            }

            @Override
            public long getSize() {
              try {
                return stat.getSize();
              } catch (IOException e) {
                throw new IllegalStateException(e);
              }
            }

            @Override
            public synchronized long getLastModifiedTime() {
              try {
                return stat.getLastModifiedTime();
              } catch (IOException e) {
                throw new IllegalStateException(e);
              }
            }

            @Override
            public synchronized long getLastChangeTime() {
              try {
                return stat.getLastChangeTime();
              } catch (IOException e) {
                throw new IllegalStateException(e);
              }
            }

            @Override
            public long getNodeId() {
              try {
                return stat.getNodeId();
              } catch (IOException e) {
                throw new IllegalStateException(e);
              }
            }
          };
        }
        return stat;
      }
    };
  }

  private Transformer createBadDirectoryListingTransformer(final String badPathSuffix) {
    return new Transformer() {
      @Nullable
      @Override
      public Collection<Dirent> readdir(
          Collection<Dirent> readdir, PathFragment path, boolean followSymlinks)
          throws IOException {
        if (path.getPathString().endsWith(badPathSuffix)) {
          throw new IOException("Path ended in " + badPathSuffix + ", so readdir failed.");
        }
        return readdir;
      }
    };
  }
}
