// 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 org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.util.BlazeClock;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * Tests {@link UnixGlob} recursive globs.
 */
@RunWith(JUnit4.class)
public class RecursiveGlobTest {

  private Path tmpPath;
  private FileSystem fileSystem;
  
  @Before
  public final void initializeFileSystem() throws Exception  {
    fileSystem = new InMemoryFileSystem(BlazeClock.instance());
    tmpPath = fileSystem.getPath("/rglobtmp");
    for (String dir : ImmutableList.of("foo/bar/wiz",
                         "foo/baz/wiz",
                         "foo/baz/quip/wiz",
                         "food/baz/wiz",
                         "fool/baz/wiz")) {
      FileSystemUtils.createDirectoryAndParents(tmpPath.getRelative(dir));
    }
    FileSystemUtils.createEmptyFile(tmpPath.getRelative("foo/bar/wiz/file"));
  }

  @Test
  public void testDoubleStar() throws Exception {
    assertGlobMatches("**", ".", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", "foo/baz/quip",
                      "foo/baz/quip/wiz", "foo/baz/wiz", "foo/bar/wiz/file", "food", "food/baz",
                      "food/baz/wiz", "fool", "fool/baz", "fool/baz/wiz");
  }

  @Test
  public void testDoubleDoubleStar() throws Exception {
    assertGlobMatches("**/**", ".", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", "foo/baz/quip",
                      "foo/baz/quip/wiz", "foo/baz/wiz", "foo/bar/wiz/file", "food", "food/baz",
                      "food/baz/wiz", "fool", "fool/baz", "fool/baz/wiz");
  }

  @Test
  public void testDirectoryWithDoubleStar() throws Exception {
    assertGlobMatches("foo/**", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", "foo/baz/quip",
                      "foo/baz/quip/wiz", "foo/baz/wiz", "foo/bar/wiz/file");
  }

  @Test
  public void testIllegalPatterns() throws Exception {
    for (String prefix : Lists.newArrayList("", "*/", "**/", "ba/")) {
      String suffix = ("/" + prefix).substring(0, prefix.length());
      for (String pattern : Lists.newArrayList("**fo", "fo**", "**fo**", "fo**fo", "fo**fo**fo")) {
        assertIllegalWildcard(prefix + pattern);
        assertIllegalWildcard(pattern + suffix);
      }
    }
  }

  @Test
  public void testDoubleStarPatternWithNamedChild() throws Exception {
    assertGlobMatches("**/bar", "foo/bar");
  }

  @Test
  public void testDoubleStarPatternWithChildGlob() throws Exception {
    assertGlobMatches("**/ba*",
        "foo/bar", "foo/baz", "food/baz", "fool/baz");
  }

  @Test
  public void testDoubleStarAsChildGlob() throws Exception {
    assertGlobMatches("foo/**/wiz", "foo/bar/wiz", "foo/baz/quip/wiz", "foo/baz/wiz");
  }

  @Test
  public void testDoubleStarUnderNonexistentDirectory() throws Exception {
    assertGlobMatches("not-there/**" /* => nothing */);
  }

  @Test
  public void testDoubleStarGlobWithNonExistentBase() throws Exception {
    Collection<Path> globResult = UnixGlob.forPath(fileSystem.getPath("/does/not/exist"))
        .addPattern("**")
        .globInterruptible();
    assertThat(globResult).isEmpty();
  }

  @Test
  public void testDoubleStarUnderFile() throws Exception {
    assertGlobMatches("foo/bar/wiz/file/**" /* => nothing */);
  }

  private void assertGlobMatches(String pattern, String... expecteds)
      throws Exception {
    assertThat(
        new UnixGlob.Builder(tmpPath)
            .addPatterns(pattern)
            .globInterruptible())
    .containsExactlyElementsIn(resolvePaths(expecteds));
  }

  private Set<Path> resolvePaths(String... relativePaths) {
    Set<Path> expectedFiles = new HashSet<>();
    for (String expected : relativePaths) {
      Path file = expected.equals(".")
          ? tmpPath
          : tmpPath.getRelative(expected);
      expectedFiles.add(file);
    }
    return expectedFiles;
  }

  @Test
  public void testRecursiveGlobsAreOptimized() throws Exception {
    long numGlobTasks = new UnixGlob.Builder(tmpPath)
        .addPattern("**")
        .setExcludeDirectories(false)
        .globInterruptibleAndReturnNumGlobTasksForTesting();

    // The old glob implementation used to use 41 total glob tasks.
    // Yes, checking for an exact value here is super brittle, but it lets us catch performance
    // regressions. In other words, if you're a developer reading this comment because this test
    // case is failing, you should be very sure you know what you're doing before you change the
    // expectation of the test.
    assertThat(numGlobTasks).isEqualTo(28);
  }

  private void assertIllegalWildcard(String pattern)
      throws Exception {
    try {
      new UnixGlob.Builder(tmpPath)
          .addPattern(pattern)
          .globInterruptible();
      fail();
    } catch (IllegalArgumentException e) {
      assertThat(e.getMessage()).containsMatch("recursive wildcard must be its own segment");
    }
  }

}
