// Copyright 2019 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.skyframe;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.FileStateValue;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.lib.vfs.RootedPathAndCasing;
import com.google.devtools.build.lib.vfs.UnixGlob;
import com.google.devtools.build.skyframe.EvaluationContext;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
import com.google.devtools.build.skyframe.RecordingDifferencer;
import com.google.devtools.build.skyframe.SequencedRecordingDifferencer;
import com.google.devtools.build.skyframe.SequentialBuildDriver;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link PathCasingLookupFunction}. */
@RunWith(JUnit4.class)
public final class PathCasingLookupFunctionTest extends FoundationTestCase {

  private SequentialBuildDriver driver;
  private RecordingDifferencer differencer;

  @Before
  public final void setUp() {
    AtomicReference<PathPackageLocator> pkgLocator =
        new AtomicReference<>(
            new PathPackageLocator(
                outputBase,
                ImmutableList.of(Root.fromPath(rootDirectory)),
                BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY));
    BlazeDirectories directories =
        new BlazeDirectories(
            new ServerDirectories(rootDirectory, outputBase, rootDirectory),
            rootDirectory,
            null,
            AnalysisMock.get().getProductName());
    ExternalFilesHelper externalFilesHelper =
        ExternalFilesHelper.createForTesting(
            pkgLocator,
            ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
            directories);

    AtomicReference<UnixGlob.FilesystemCalls> syscalls =
        new AtomicReference<>(UnixGlob.DEFAULT_SYSCALLS);
    Map<SkyFunctionName, SkyFunction> skyFunctions = new HashMap<>();
    skyFunctions.put(
        FileStateValue.FILE_STATE,
        new FileStateFunction(new AtomicReference<>(), syscalls, externalFilesHelper));
    skyFunctions.put(FileValue.FILE, new FileFunction(pkgLocator));
    skyFunctions.put(SkyFunctions.DIRECTORY_LISTING, new DirectoryListingFunction());
    skyFunctions.put(
        SkyFunctions.DIRECTORY_LISTING_STATE,
        new DirectoryListingStateFunction(externalFilesHelper, syscalls));
    skyFunctions.put(SkyFunctions.PATH_CASING_LOOKUP, new PathCasingLookupFunction());

    differencer = new SequencedRecordingDifferencer();
    driver =
        new SequentialBuildDriver(new InMemoryMemoizingEvaluator(skyFunctions, differencer, null));
  }

  private RootedPath rootedPath(String relative) {
    return RootedPath.toRootedPath(Root.fromPath(rootDirectory), PathFragment.create(relative));
  }

  @Test
  public void testSanityCheckFilesystemIsCaseInsensitive() {
    Path p1 = rootDirectory.getRelative("Foo/Bar");
    Path p2 = rootDirectory.getRelative("FOO/BAR");
    Path p3 = rootDirectory.getRelative("control");
    assertThat(p1).isNotSameInstanceAs(p2);
    assertThat(p1).isNotSameInstanceAs(p3);
    assertThat(p2).isNotSameInstanceAs(p3);
    assertThat(p1).isEqualTo(p2);
    assertThat(p1).isNotEqualTo(p3);
  }

  @Test
  public void testPathCasingLookup() throws Exception {
    RootedPath a = rootedPath("Foo/Bar/Baz");
    RootedPath b = rootedPath("fOO/baR/BAZ");
    createFile(a);
    assertThat(a).isEqualTo(b);
    assertThat(RootedPathAndCasing.create(a)).isNotEqualTo(RootedPathAndCasing.create(b));
    assertThat(expectEvalSuccess(a).isCorrect()).isTrue();
    assertThat(expectEvalSuccess(b).isCorrect()).isFalse();
  }

  @Test
  public void testNonExistentPath() throws Exception {
    RootedPath file = rootedPath("Foo/Bar/Baz.txt");
    createFile(file);
    RootedPath missing1 = rootedPath("Foo/Bar/x/y");
    RootedPath missing2 = rootedPath("Foo/BAR/x/y");
    // Non-existent paths are correct if their existing part is correct.
    assertThat(expectEvalSuccess(missing1).isCorrect()).isTrue();
    assertThat(expectEvalSuccess(missing2).isCorrect()).isFalse();
    // Non-existent paths are illegal if their parent exists but is not a directory.
    RootedPath bad = rootedPath("Foo/Bar/Baz.txt/x/y");
    Exception e = expectEvalFailure(bad);
    assertThat(e).hasMessageThat().contains("its parent exists but is not a directory");
  }

  @Test
  public void testNonExistentPathThatComesIntoExistence() throws Exception {
    RootedPath a = rootedPath("Foo/Bar/Baz");
    RootedPath b = rootedPath("fOO/baR/BAZ");
    assertThat(a).isEqualTo(b);
    // Expecting RootedPath.toRootedPath not to intern instances, otherwise 'a' would be the same
    // instance as 'b' which would nullify this test.
    assertThat(a).isNotSameInstanceAs(b);
    assertThat(a.toString()).isNotEqualTo(b.toString());
    assertThat(RootedPathAndCasing.create(a)).isNotEqualTo(RootedPathAndCasing.create(b));
    // Path does not exist, so both casings are correct!
    assertThat(expectEvalSuccess(a).isCorrect()).isTrue();
    assertThat(expectEvalSuccess(b).isCorrect()).isTrue();
    // Path comes into existence.
    createFile(a);
    // Now only one casing is correct.
    assertThat(expectEvalSuccess(a).isCorrect()).isTrue();
    assertThat(expectEvalSuccess(b).isCorrect()).isFalse();
  }

  @Test
  public void testExistingPathThatIsThenDeleted() throws Exception {
    RootedPath a = rootedPath("Foo/Bar/Baz");
    RootedPath b = rootedPath("Foo/Bar/BAZ");
    createFile(a);
    // Path exists, so only one casing is correct.
    assertThat(expectEvalSuccess(a).isCorrect()).isTrue();
    assertThat(expectEvalSuccess(b).isCorrect()).isFalse();
    // Path no longer exists, both casings are correct.
    deleteFile(a);
    assertThat(expectEvalSuccess(a).isCorrect()).isTrue();
    assertThat(expectEvalSuccess(b).isCorrect()).isTrue();
  }

  private void createFile(RootedPath p) throws IOException {
    Path path = p.asPath();
    if (!path.getParentDirectory().exists()) {
      scratch.dir(path.getParentDirectory().getPathString());
    }
    scratch.file(path.getPathString());
    invalidateFileAndParents(p);
  }

  private void deleteFile(RootedPath p) throws IOException {
    Path path = p.asPath();
    scratch.deleteFile(path.getPathString());
    invalidateFileAndParents(p);
  }

  private EvaluationResult<PathCasingLookupValue> evaluate(SkyKey key) throws Exception {
    EvaluationContext evaluationContext =
        EvaluationContext.newBuilder()
            .setKeepGoing(false)
            .setNumThreads(SkyframeExecutor.DEFAULT_THREAD_COUNT)
            .setEventHander(NullEventHandler.INSTANCE)
            .build();
    return driver.evaluate(ImmutableList.of(key), evaluationContext);
  }

  private PathCasingLookupValue expectEvalSuccess(RootedPath path) throws Exception {
    SkyKey key = PathCasingLookupValue.key(path);
    EvaluationResult<PathCasingLookupValue> result = evaluate(key);
    assertThat(result.hasError()).isFalse();
    return result.get(key);
  }

  private Exception expectEvalFailure(RootedPath path) throws Exception {
    SkyKey key = PathCasingLookupValue.key(path);
    EvaluationResult<PathCasingLookupValue> result = evaluate(key);
    assertThat(result.hasError()).isTrue();
    return result.getError().getException();
  }

  private void invalidateFile(RootedPath path) {
    differencer.invalidate(ImmutableList.of(FileStateValue.key(path)));
  }

  private void invalidateDirectory(RootedPath path) {
    invalidateFile(path);
    differencer.invalidate(ImmutableList.of(DirectoryListingStateValue.key(path)));
  }

  private void invalidateFileAndParents(RootedPath p) {
    invalidateFile(p);
    do {
      p = p.getParentDirectory();
      invalidateDirectory(p);
    } while (!p.getRootRelativePath().isEmpty());
  }
}
