// Copyright 2022 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 static org.junit.Assert.assertThrows;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.buildtool.util.BuildIntegrationTestCase;
import com.google.devtools.build.lib.skyframe.DiffAwareness.View;
import com.google.devtools.build.lib.skyframe.LocalDiffAwareness.SequentialView;
import com.google.devtools.build.lib.testing.common.FakeOptions;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
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.common.options.OptionsProvider;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Set;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Integration tests for LocalDiffAwareness.
 */
@RunWith(JUnit4.class)
public class LocalDiffAwarenessTest extends BuildIntegrationTestCase {

  /** Try this many times to pick up file changes. Inotify needs some nanoseconds of patience. */
  private static final int MAX_RETRY_COUNT = 20;

  private OptionsProvider watchFsEnabledProvider;
  private LocalDiffAwareness localDiff;
  private DiffAwareness.View oldView;
  private Path testCaseRoot;

  @org.junit.Rule
  public TestName name = new TestName();

  @Before
  public final void initializeSettings() throws Exception  {
    LocalDiffAwareness.Factory factory = new LocalDiffAwareness.Factory(ImmutableList.<String>of());
    // Make sure all test functions have their own directory to test
    testCaseRoot = testRoot.getChild(name.getMethodName());
    testCaseRoot.createDirectoryAndParents();
    localDiff = (LocalDiffAwareness) factory.maybeCreate(Root.fromPath(testCaseRoot));

    LocalDiffAwareness.Options localDiffOptions = new LocalDiffAwareness.Options();
    localDiffOptions.watchFS = true;
    watchFsEnabledProvider = FakeOptions.of(localDiffOptions);

    // Ignore test failures when run on a Mac.
    //
    // On a Mac, LocalDiffAwareness.Factory#maybeCreate will produce a MacOSXFsEventsDiffAwareness.
    // There's a known issue with the underlying implementation
    // (https://github.com/bazelbuild/bazel/issues/10776); basically all the test cases in here
    // consistently fail, presumably due to the same underlying issue with FSEvents. Also,
    // MacOSXFsEventsDiffAwareness is already unit-tested separately anyway (although not very well
    // because of the bug).
    Assume.assumeFalse(OS.DARWIN.equals(OS.getCurrent()));
  }

  @After
  public final void closeLocalDiff() throws Exception {
    localDiff.close();
  }

  @After
  public final void deleteTestCaseRoot() throws Exception {
    testCaseRoot.deleteTree();
  }

  private void captureFirstView(OptionsProvider options) throws BrokenDiffAwarenessException {
    oldView = localDiff.getCurrentView(options);
    Preconditions.checkNotNull(localDiff);
  }

  @Test
  public void areInSequenceWithEverythingModifiedShouldAlwaysReturnFalse() throws Exception {
    captureFirstView(watchFsEnabledProvider);
    SequentialView old = (SequentialView) oldView;
    SequentialView everythingMod = (SequentialView) LocalDiffAwareness.EVERYTHING_MODIFIED;
    assertThat(LocalDiffAwareness.areInSequence(old, everythingMod)).isFalse();
    assertThat(LocalDiffAwareness.areInSequence(everythingMod, old)).isFalse();
    assertThat(LocalDiffAwareness.areInSequence(everythingMod, everythingMod)).isFalse();
  }

  @Test
  public void testFileAdded() throws Exception {
    captureFirstView(watchFsEnabledProvider);
    touch("foo.txt");
    new ModifiedFileSetChecker().modify("foo.txt").check();
  }

  @Test
  public void testSymlink() throws Exception {
    captureFirstView(watchFsEnabledProvider);
    touch("a");
    symlink("b", "a");
    new ModifiedFileSetChecker().modify("a").modify("b").check();
  }

  @Test
  public void testSymlinkBroken() throws Exception {
    captureFirstView(watchFsEnabledProvider);
    symlink("b", "a");
    new ModifiedFileSetChecker().modify("b").check();
  }

  @Test
  public void testFileModified() throws Exception {
    captureFirstView(watchFsEnabledProvider);

    touch("foo.txt");
    new ModifiedFileSetChecker().modify("foo.txt").check();

    new ModifiedFileSetChecker().check();

    touch("foo.txt");
    new ModifiedFileSetChecker().modify("foo.txt").check();
  }

  @Test
  public void testFileRemoved() throws Exception {
    captureFirstView(watchFsEnabledProvider);

    touch("foo.txt");
    new ModifiedFileSetChecker().modify("foo.txt").check();

    rm("foo.txt");
    new ModifiedFileSetChecker().modify("foo.txt").check();
  }

  @Test
  public void testFileAddAndRemove() throws Exception {
    captureFirstView(watchFsEnabledProvider);

    touch("foo.txt");
    touch("bar.txt");
    new ModifiedFileSetChecker().modify("foo.txt").modify("bar.txt").check();

    rm("foo.txt");
    touch("foo.txt");
    new ModifiedFileSetChecker().modify("foo.txt").check();
  }

  @Test
  public void testAddDirectory() throws Exception {
    captureFirstView(watchFsEnabledProvider);

    mkdir("equestria");
    touch("equestria/foo.txt");
    new ModifiedFileSetChecker().modify("equestria").modify("equestria/foo.txt").check();
  }

  @Test
  public void testRemoveDirectory() throws Exception {
    captureFirstView(watchFsEnabledProvider);

    mkdir("equestria");
    touch("equestria/foo.txt");
    new ModifiedFileSetChecker().modify("equestria").modify("equestria/foo.txt").check();


    rm("equestria");
    new ModifiedFileSetChecker().modify("equestria").modify("equestria/foo.txt").check();
  }

  @Test
  public void testLotsOfChanges() throws Exception {
    captureFirstView(watchFsEnabledProvider);

    mkdir("pre");
    touch("pre/pre.txt");
    new ModifiedFileSetChecker().modify("pre").modify("pre/pre.txt").check();

    mkdir("a");
    touch("a/a1.txt");
    touch("a/a2.txt");
    rm("a");
    mkdir("a");
    touch("a/a1.txt");
    touch("a/a2.txt");
    mkdir("a/b");
    touch("a/b/b1.txt");
    new ModifiedFileSetChecker()
    .modify("a")
    .modify("a/a1.txt")
    .modify("a/a2.txt")
    .modify("a/b")
    .modify("a/b/b1.txt")
    .check();

    rm("a/b/b1.txt");
    touch("a/b/b2.txt");
    rm("a/b");
    mkdir("a/b");
    rm("a/b");
    mkdir("a/b");
    touch("a/b/b3.txt");
    new ModifiedFileSetChecker()
    .modify("a/b")
    .modify("a/b/b1.txt")
    .modify("a/b/b2.txt")
    .modify("a/b/b3.txt")
    .check();

    rm("a/b/b3.txt");
    new ModifiedFileSetChecker().modify("a/b/b3.txt").check();
  }

  private static OptionsProvider createWatchFsDisabledProvider() {
    final LocalDiffAwareness.Options localDiffOptions = new LocalDiffAwareness.Options();
    localDiffOptions.watchFS = false;
    return FakeOptions.of(localDiffOptions);
  }

  @Test
  public void testEnableWatchFs() throws Exception {
    OptionsProvider watchFsDisabledProvider = createWatchFsDisabledProvider();
    captureFirstView(watchFsDisabledProvider);

    new ModifiedFileSetChecker().checkEverythingModified(watchFsDisabledProvider);

    touch("a.txt");
    new ModifiedFileSetChecker().checkEverythingModified(watchFsDisabledProvider);

    touch("b.txt");
    new ModifiedFileSetChecker().checkEverythingModified(watchFsEnabledProvider);

    touch("c.txt");
    new ModifiedFileSetChecker().modify("c.txt").check();
  }

  @Test
  public void testDisableWatchFs() throws Exception {
    OptionsProvider watchFsDisabledProvider = createWatchFsDisabledProvider();
    captureFirstView(watchFsEnabledProvider);

    new ModifiedFileSetChecker().check();

    assertThrows(
        BrokenDiffAwarenessException.class,
        () -> localDiff.getCurrentView(watchFsDisabledProvider));
  }

  @Test
  public void modifiedPathIsntUnderWatchRoot() {
    java.nio.file.Path otherRootDirectoryNioPath = Paths.get("/notundertestroot");
    assertThat(otherRootDirectoryNioPath.startsWith(Paths.get(testCaseRoot.getPathString())))
        .isFalse();

    View oldView =
        new LocalDiffAwareness.SequentialView(
            localDiff, /*position=*/ 0, /*modifiedAbsolutePaths=*/ ImmutableSet.of());
    View newView =
        new LocalDiffAwareness.SequentialView(
            localDiff,
            /*position=*/ 1,
            /*modifiedAbsolutePaths=*/ ImmutableSet.of(
                otherRootDirectoryNioPath.resolve("foo.txt")));
    Throwable throwable =
        assertThrows(BrokenDiffAwarenessException.class, () -> localDiff.getDiff(oldView, newView));
    assertThat(throwable)
        .hasMessageThat()
        // Do a round-trip through PathFragment to deal with Windows path separators.
        .contains(
            PathFragment.create("/notundertestroot/foo.txt is not under ").getPathString()
                + PathFragment.create(testCaseRoot.getPathString()).getPathString());
  }

  private void touch(String pathString) throws IOException {
    Path path = testCaseRoot.getRelative(pathString);
    FileSystemUtils.createEmptyFile(path);
    FileSystemUtils.writeIsoLatin1(path, "Sunshine, sunshine, ladybugs awake!");
  }

  private void mkdir(String pathString) throws IOException {
    Path path = testCaseRoot.getRelative(pathString);
    path.createDirectoryAndParents();
  }

  private void rm(String pathString) throws IOException {
    Path path = testCaseRoot.getRelative(pathString);
    path.deleteTree();
  }

  private void symlink(String from, String to) throws IOException {
    Path fromPath = testCaseRoot.getRelative(from);
    Path toPath = testCaseRoot.getRelative(to);
    FileSystemUtils.ensureSymbolicLink(fromPath, toPath);
  }

  private class ModifiedFileSetChecker {
    private final Set<PathFragment> modified = Sets.newHashSet();

    public void check() throws Exception {
      // Unfortunately, inotify needs a few milliseconds (more than a few in the worst case)
      // after a change to pick up a list of changed files. Trying a few times to make sure.
      for (int i = 0; i < MAX_RETRY_COUNT; i++) {
        Thread.sleep(150);
        DiffAwareness.View newView = localDiff.getCurrentView(watchFsEnabledProvider);
        ModifiedFileSet modifiedFileSet = localDiff.getDiff(oldView, newView);
        oldView = newView;
        assertThat(modifiedFileSet.treatEverythingAsModified()).isFalse();
        if (modifiedFileSet.modifiedSourceFiles().isEmpty()) {
          continue;
        }
        assertThat(modifiedFileSet.modifiedSourceFiles()).isEqualTo(modified);
        return;
      }
      // If we never received any changes, make sure this is what we actually expect.
      assertThat(modified).isEmpty();
    }

    public void checkEverythingModified(OptionsProvider options) throws Exception {
      DiffAwareness.View newView = localDiff.getCurrentView(options);
      ModifiedFileSet modifiedFileSet = localDiff.getDiff(oldView, newView);
      oldView = newView;
      assertThat(modifiedFileSet.treatEverythingAsModified()).isTrue();
    }

    public ModifiedFileSetChecker modify(String filename) {
      modified.add(PathFragment.create(filename));
      return this;
    }
  }
}
