/* * Copyright 2014-present Facebook, Inc. * * 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.facebook.buck.parser; import static org.junit.Assert.assertEquals; import com.facebook.buck.config.Config; import com.facebook.buck.config.ConfigBuilder; import com.facebook.buck.io.FakeWatchmanClient; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.io.ProjectWatch; import com.facebook.buck.io.Watchman; import com.facebook.buck.rules.Cell; import com.facebook.buck.rules.TestCellBuilder; import com.facebook.buck.testutil.FakeProjectFilesystem; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import java.util.concurrent.TimeUnit; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; public class BuildFileSpecTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Rule public TemporaryFolder tmp = new TemporaryFolder(); @Test public void recursiveVsNonRecursive() throws IOException, InterruptedException { FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); Path buildFile = Paths.get("a", "BUCK"); filesystem.mkdirs(buildFile.getParent()); filesystem.touch(buildFile); Path nestedBuildFile = Paths.get("a", "b", "BUCK"); filesystem.mkdirs(nestedBuildFile.getParent()); filesystem.touch(nestedBuildFile); // Test a non-recursive spec. BuildFileSpec nonRecursiveSpec = BuildFileSpec.fromPath(buildFile.getParent(), filesystem.getRootPath()); ImmutableSet<Path> expectedBuildFiles = ImmutableSet.of(filesystem.resolve(buildFile)); Cell cell = new TestCellBuilder().setFilesystem(filesystem).build(); ImmutableSet<Path> actualBuildFiles = nonRecursiveSpec.findBuildFiles(cell, ParserConfig.BuildFileSearchMethod.FILESYSTEM_CRAWL); assertEquals(expectedBuildFiles, actualBuildFiles); // Test a recursive spec. BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent(), filesystem.getRootPath()); expectedBuildFiles = ImmutableSet.of(filesystem.resolve(buildFile), filesystem.resolve(nestedBuildFile)); actualBuildFiles = recursiveSpec.findBuildFiles(cell, ParserConfig.BuildFileSearchMethod.FILESYSTEM_CRAWL); assertEquals(expectedBuildFiles, actualBuildFiles); } @Test public void recursiveIgnorePaths() throws IOException, InterruptedException { Path ignoredBuildFile = Paths.get("a", "b", "BUCK"); Config config = ConfigBuilder.createFromText("[project]", "ignore = a/b"); ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot().toPath(), config); Path buildFile = Paths.get("a", "BUCK"); filesystem.mkdirs(buildFile.getParent()); filesystem.writeContentsToPath("", buildFile); filesystem.mkdirs(ignoredBuildFile.getParent()); filesystem.writeContentsToPath("", ignoredBuildFile); // Test a recursive spec with an ignored dir. BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent(), filesystem.getRootPath()); ImmutableSet<Path> expectedBuildFiles = ImmutableSet.of(filesystem.resolve(buildFile)); Cell cell = new TestCellBuilder().setFilesystem(filesystem).build(); ImmutableSet<Path> actualBuildFiles = recursiveSpec.findBuildFiles(cell, ParserConfig.BuildFileSearchMethod.FILESYSTEM_CRAWL); assertEquals(expectedBuildFiles, actualBuildFiles); } @Test public void findWithWatchmanSucceeds() throws IOException, InterruptedException { Path watchRoot = Paths.get(".").toAbsolutePath().normalize(); FakeProjectFilesystem filesystem = new FakeProjectFilesystem(watchRoot.resolve("project-name")); Path buildFile = Paths.get("a", "BUCK"); BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent(), filesystem.getRootPath()); ImmutableSet<Path> expectedBuildFiles = ImmutableSet.of(filesystem.resolve(buildFile)); FakeWatchmanClient fakeWatchmanClient = new FakeWatchmanClient( 0, ImmutableMap.of( ImmutableList.of( "query", watchRoot.toString(), ImmutableMap.of( "relative_root", "project-name", "sync_timeout", 0, "path", ImmutableList.of("a"), "fields", ImmutableList.of("name"), "expression", ImmutableList.of( "allof", "exists", ImmutableList.of("name", "BUCK"), ImmutableList.of("type", "f")))), ImmutableMap.of("files", ImmutableList.of("a/BUCK")))); Cell cell = new TestCellBuilder() .setFilesystem(filesystem) .setWatchman( new Watchman( ImmutableMap.of( filesystem.getRootPath(), ProjectWatch.of(watchRoot.toString(), Optional.of("project-name"))), ImmutableSet.of( Watchman.Capability.SUPPORTS_PROJECT_WATCH, Watchman.Capability.DIRNAME, Watchman.Capability.WILDMATCH_GLOB), ImmutableMap.of(), Optional.of(Paths.get(".watchman-sock")), Optional.of(fakeWatchmanClient))) .build(); ImmutableSet<Path> actualBuildFiles = recursiveSpec.findBuildFiles(cell, ParserConfig.BuildFileSearchMethod.WATCHMAN); assertEquals(expectedBuildFiles, actualBuildFiles); } @Test public void findWithWatchmanThrowsOnFailure() throws IOException, InterruptedException { Path watchRoot = Paths.get(".").toAbsolutePath().normalize(); FakeProjectFilesystem filesystem = new FakeProjectFilesystem(watchRoot.resolve("project-name")); Path buildFile = Paths.get("a", "BUCK"); BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent(), filesystem.getRootPath()); FakeWatchmanClient fakeWatchmanClient = new FakeWatchmanClient( 0, ImmutableMap.of( ImmutableList.of( "query", watchRoot.toString(), ImmutableMap.of( "relative_root", "project-name", "sync_timeout", 0, "path", ImmutableList.of("a"), "fields", ImmutableList.of("name"), "expression", ImmutableList.of( "allof", "exists", ImmutableList.of("name", "BUCK"), ImmutableList.of("type", "f")))), ImmutableMap.of("files", ImmutableList.of("a/BUCK"))), new IOException("Whoopsie!")); Cell cell = new TestCellBuilder() .setFilesystem(filesystem) .setWatchman( new Watchman( ImmutableMap.of( filesystem.getRootPath(), ProjectWatch.of(watchRoot.toString(), Optional.of("project-name"))), ImmutableSet.of( Watchman.Capability.SUPPORTS_PROJECT_WATCH, Watchman.Capability.DIRNAME, Watchman.Capability.WILDMATCH_GLOB), ImmutableMap.of(), Optional.of(Paths.get(".watchman-sock")), Optional.of(fakeWatchmanClient))) .build(); thrown.expect(IOException.class); thrown.expectMessage("Whoopsie!"); recursiveSpec.findBuildFiles(cell, ParserConfig.BuildFileSearchMethod.WATCHMAN); } @Test public void findWithWatchmanFallsBackToFilesystemOnTimeout() throws IOException, InterruptedException { Path watchRoot = Paths.get(".").toAbsolutePath().normalize(); FakeProjectFilesystem filesystem = new FakeProjectFilesystem(watchRoot.resolve("project-name")); Path buildFile = Paths.get("a", "BUCK"); filesystem.mkdirs(buildFile.getParent()); filesystem.touch(buildFile); Path nestedBuildFile = Paths.get("a", "b", "BUCK"); filesystem.mkdirs(nestedBuildFile.getParent()); filesystem.touch(nestedBuildFile); BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent(), filesystem.getRootPath()); FakeWatchmanClient timingOutWatchmanClient = new FakeWatchmanClient( // Pretend the query takes a very very long time. TimeUnit.SECONDS.toNanos(Long.MAX_VALUE), ImmutableMap.of( ImmutableList.of( "query", watchRoot.toString(), ImmutableMap.of( "relative_root", "project-name", "sync_timeout", 0, "path", ImmutableList.of("a"), "fields", ImmutableList.of("name"), "expression", ImmutableList.of( "allof", "exists", ImmutableList.of("name", "BUCK"), ImmutableList.of("type", "f")))), ImmutableMap.of("files", ImmutableList.of("a/BUCK", "a/b/BUCK")))); Cell cell = new TestCellBuilder() .setFilesystem(filesystem) .setWatchman( new Watchman( ImmutableMap.of( filesystem.getRootPath(), ProjectWatch.of(watchRoot.toString(), Optional.of("project-name"))), ImmutableSet.of( Watchman.Capability.SUPPORTS_PROJECT_WATCH, Watchman.Capability.DIRNAME, Watchman.Capability.WILDMATCH_GLOB), ImmutableMap.of(), Optional.of(Paths.get(".watchman-sock")), Optional.of(timingOutWatchmanClient))) .build(); ImmutableSet<Path> expectedBuildFiles = ImmutableSet.of(filesystem.resolve(buildFile), filesystem.resolve(nestedBuildFile)); ImmutableSet<Path> actualBuildFiles = recursiveSpec.findBuildFiles(cell, ParserConfig.BuildFileSearchMethod.WATCHMAN); assertEquals(expectedBuildFiles, actualBuildFiles); } }