@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()); ImmutableSet<Path> expectedBuildFiles = ImmutableSet.of(filesystem.resolve(buildFile)); Cell cell = new TestCellBuilder().setFilesystem(filesystem).build(); ImmutableSet<Path> actualBuildFiles = nonRecursiveSpec.findBuildFiles(cell); assertEquals(expectedBuildFiles, actualBuildFiles); // Test a recursive spec. BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent()); expectedBuildFiles = ImmutableSet.of(filesystem.resolve(buildFile), filesystem.resolve(nestedBuildFile)); actualBuildFiles = recursiveSpec.findBuildFiles(cell); assertEquals(expectedBuildFiles, actualBuildFiles); }
/** Ensure that build rules with the same inputs but different deps have unique RuleKeys. */ @Test public void testRuleKeyDependsOnDeps() throws Exception { FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); FileHashCache hashCache = new DefaultFileHashCache(filesystem); BuildRuleResolver ruleResolver1 = new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer()); BuildRuleResolver ruleResolver2 = new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer()); RuleKeyBuilderFactory ruleKeyBuilderFactory1 = new DefaultRuleKeyBuilderFactory(hashCache, new SourcePathResolver(ruleResolver1)); RuleKeyBuilderFactory ruleKeyBuilderFactory2 = new DefaultRuleKeyBuilderFactory(hashCache, new SourcePathResolver(ruleResolver2)); // Create a dependent build rule, //src/com/facebook/buck/cli:common. JavaLibraryBuilder builder = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//src/com/facebook/buck/cli:common")); BuildRule commonJavaLibrary = builder.build(ruleResolver1); builder.build(ruleResolver2); // Create a java_library() rule with no deps. Path mainSrc = Paths.get("src/com/facebook/buck/cli/Main.java"); filesystem.mkdirs(mainSrc.getParent()); filesystem.writeContentsToPath("hello", mainSrc); JavaLibraryBuilder javaLibraryBuilder = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//src/com/facebook/buck/cli:cli")) .addSrc(mainSrc); BuildRule libraryNoCommon = javaLibraryBuilder.build(ruleResolver1, filesystem); // Create the same java_library() rule, but with a dep on //src/com/facebook/buck/cli:common. javaLibraryBuilder.addDep(commonJavaLibrary.getBuildTarget()); BuildRule libraryWithCommon = javaLibraryBuilder.build(ruleResolver2, filesystem); // Assert that the RuleKeys are distinct. RuleKey r1 = ruleKeyBuilderFactory1.build(libraryNoCommon); RuleKey r2 = ruleKeyBuilderFactory2.build(libraryWithCommon); assertThat( "Rule keys should be distinct because the deps of the rules are different.", r1, not(equalTo(r2))); }
@Test public void createBuildRuleWithFlavoredTargetCallsEnhancerCorrectly() throws IOException { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); // Setup the default values returned by the language specific enhancer. String language = "fake"; Flavor flavor = ImmutableFlavor.of("fake"); final BuildRule implicitDep = createFakeBuildRule("//implicit:dep", pathResolver); resolver.addToIndex(implicitDep); filesystem.mkdirs(implicitDep.getBuildTarget().getBasePath()); filesystem.touch(implicitDep.getBuildTarget().getBasePath().resolve("BUCK")); ImmutableSet<BuildTarget> implicitDeps = ImmutableSet.of(implicitDep.getBuildTarget()); ImmutableSet<String> options = ImmutableSet.of(); // Create the build targets and params. BuildTarget unflavoredTarget = BuildTargetFactory.newInstance("//:thrift"); BuildRuleParams unflavoredParams = new FakeBuildRuleParamsBuilder(unflavoredTarget).setProjectFilesystem(filesystem).build(); BuildTarget flavoredTarget = BuildTargets.createFlavoredBuildTarget(unflavoredTarget.checkUnflavored(), flavor); BuildRuleParams flavoredParams = new FakeBuildRuleParamsBuilder(flavoredTarget).setProjectFilesystem(filesystem).build(); // Setup a thrift source file generated by a genrule. final String thriftSourceName1 = "foo.thrift"; BuildTarget genruleTarget = BuildTargetFactory.newInstance("//:genrule"); final Genrule genrule = (Genrule) GenruleBuilder.newGenruleBuilder(genruleTarget) .setOut(thriftSourceName1) .build(resolver); SourcePath thriftSource1 = new BuildTargetSourcePath(genrule.getBuildTarget()); final ImmutableList<String> thriftServices1 = ImmutableList.of(); // Setup a normal thrift source file. final String thriftSourceName2 = "bar.thrift"; SourcePath thriftSource2 = new TestSourcePath(thriftSourceName2); final ImmutableList<String> thriftServices2 = ImmutableList.of(); // Create a build rule that represents the thrift rule. final FakeBuildRule thriftRule = createFakeBuildRule("//thrift:target", pathResolver); resolver.addToIndex(thriftRule); filesystem.mkdirs(thriftRule.getBuildTarget().getBasePath()); filesystem.touch(thriftRule.getBuildTarget().getBasePath().resolve("BUCK")); // Setup a simple description with an empty config. FakeBuckConfig buckConfig = new FakeBuckConfig( ImmutableMap.of( "thrift", ImmutableMap.of("compiler", thriftRule.getBuildTarget().toString()))); ThriftBuckConfig thriftBuckConfig = new ThriftBuckConfig(buckConfig); ThriftLibraryDescription desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of()); // Setup the include rules. final BuildRule thriftIncludeSymlinkTree = createFakeBuildRule( desc.createThriftIncludeSymlinkTreeTarget(unflavoredTarget), pathResolver); // Setup our language enhancer FakeThriftLanguageSpecificEnhancer enhancer = new FakeThriftLanguageSpecificEnhancer(language, flavor, implicitDeps, options) { @Override public void checkCreateBuildRuleInputs( ImmutableMap<String, ThriftSource> sources, ImmutableSortedSet<BuildRule> deps) { // Verify both thrift sources are present in the list. assertEquals(2, sources.size()); ThriftSource src1 = sources.get(thriftSourceName1); assertNotNull(src1); ThriftSource src2 = sources.get(thriftSourceName2); assertNotNull(src2); // Verify the services are listed correctly for both sources. assertEquals(thriftServices1, src1.getServices()); assertEquals(thriftServices2, src2.getServices()); // Verify dependencies are setup correctly. assertEquals( ImmutableSortedSet.of(genrule, thriftRule, thriftIncludeSymlinkTree), src1.getCompileRule().getDeps()); assertEquals( ImmutableSortedSet.of(genrule, thriftRule, thriftIncludeSymlinkTree), src2.getCompileRule().getDeps()); // Verify the language specific implicit rules are added correctly. assertEquals( ImmutableSortedSet.<BuildRule>naturalOrder().add(implicitDep).build(), deps); } }; // Recreate the description with the enhancer we setup above. desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of(enhancer)); // Setup the internal structure indicating that the thrift target was set in the // buck config. // desc.setCompilerTarget(thriftRule.getBuildTarget()); // Setup the implicit deps for the flavored build target. // desc.setImplicitDeps(flavoredTarget, ImmutableList.of(implicitDep.getBuildTarget())); // Build up the constructor arg. ThriftConstructorArg arg = desc.createUnpopulatedConstructorArg(); arg.name = "thrift"; arg.srcs = ImmutableMap.of( thriftSource1, thriftServices1, thriftSource2, thriftServices2); arg.deps = Optional.absent(); arg.flags = Optional.absent(); // Setup the unflavored target, which should just produce a ThriftInclude, SymlinkTree, and // ThriftLibrary rule. BuildRule rule = desc.createBuildRule(TargetGraph.EMPTY, unflavoredParams, resolver, arg); resolver.addToIndex(rule); // Now attempt to create the flavored thrift library. desc.createBuildRule(TargetGraph.EMPTY, flavoredParams, resolver, arg); }
@Test public void createThriftCompilerBuildRulesHasCorrectDeps() throws IOException { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); String language = "fake"; Flavor flavor = ImmutableFlavor.of("fake"); ImmutableSet<String> options = ImmutableSet.of(); // Setup the default values returned by the language specific enhancer. BuildTarget unflavoredTarget = BuildTargetFactory.newInstance("//:thrift"); BuildRuleParams unflavoredParams = new FakeBuildRuleParamsBuilder(BuildTarget.builder(unflavoredTarget).build()) .setProjectFilesystem(filesystem) .build(); // Setup a thrift source file generated by a genrule. BuildTarget flavoredTarget = BuildTargets.createFlavoredBuildTarget(unflavoredTarget.checkUnflavored(), flavor); BuildRuleParams flavoredParams = new FakeBuildRuleParamsBuilder(flavoredTarget).setProjectFilesystem(filesystem).build(); // Create a path for the thrift compiler. Path thriftPath = Paths.get("thrift_path"); filesystem.touch(thriftPath); // Setup an thrift buck config, with the path to the thrift compiler set. FakeBuckConfig buckConfig = new FakeBuckConfig( ImmutableMap.of("thrift", ImmutableMap.of("compiler", thriftPath.toString())), filesystem); ThriftBuckConfig thriftBuckConfig = new ThriftBuckConfig(buckConfig); ThriftLibraryDescription desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of()); // Setup a simple thrift source. String sourceName = "test.thrift"; SourcePath sourcePath = new TestSourcePath(sourceName); // Generate these rules using no deps. ImmutableMap<String, ThriftCompiler> rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, sourcePath), ImmutableSortedSet.<ThriftLibrary>of()); // Now verify that the generated rule had no associated deps. assertSame(rules.size(), 1); ThriftCompiler rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(), rule.getDeps()); // Lets do this again, but pass in a ThriftLibrary deps, wrapping some includes we need. Path includeRoot = desc.getIncludeRoot(unflavoredTarget); HeaderSymlinkTree thriftIncludeSymlinkTree = createFakeSymlinkTree( desc.createThriftIncludeSymlinkTreeTarget(unflavoredTarget), pathResolver, includeRoot); ThriftLibrary lib = new ThriftLibrary( unflavoredParams, pathResolver, ImmutableSortedSet.<ThriftLibrary>of(), thriftIncludeSymlinkTree, ImmutableMap.<Path, SourcePath>of()); // Generate these rules using no deps. rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, sourcePath), ImmutableSortedSet.of(lib)); // Now verify that the generated rule has all the deps from the passed in thrift library. assertSame(rules.size(), 1); rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(thriftIncludeSymlinkTree), rule.getDeps()); // Setup a simple genrule that creates the thrift source and verify its dep is propagated. Genrule genrule = (Genrule) GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:genrule")) .setOut(sourceName) .build(resolver); SourcePath ruleSourcePath = new BuildTargetSourcePath(genrule.getBuildTarget()); // Generate these rules using no deps and the genrule generated source. rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, ruleSourcePath), ImmutableSortedSet.<ThriftLibrary>of()); // Now verify that the generated rule had no associated deps. assertSame(rules.size(), 1); rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(genrule), rule.getDeps()); // Create a build rule that represents the thrift rule. FakeBuildRule thriftRule = createFakeBuildRule("//thrift:target", pathResolver); resolver.addToIndex(thriftRule); filesystem.mkdirs(thriftRule.getBuildTarget().getBasePath()); filesystem.touch(thriftRule.getBuildTarget().getBasePath().resolve("BUCK")); // Setup an empty thrift buck config, and set compiler target. buckConfig = new FakeBuckConfig( ImmutableMap.of( "thrift", ImmutableMap.of("compiler", thriftRule.getBuildTarget().toString())), filesystem); thriftBuckConfig = new ThriftBuckConfig(buckConfig); desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of()); // Generate these rules using no deps with a compiler target. rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, sourcePath), ImmutableSortedSet.<ThriftLibrary>of()); // Now verify that the generated rule only has deps from the compiler target. assertSame(rules.size(), 1); rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(thriftRule), rule.getDeps()); }