@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); }
@Test public void invalidSourcePathShouldGiveSpecificErrorMsg() throws NoSuchFieldException { Type type = TestFields.class.getField("setOfSourcePaths").getGenericType(); TypeCoercer<?> coercer = typeCoercerFactory.typeCoercerForType(type); Path baratheon = Paths.get("Baratheon.java"); Path lannister = Paths.get("Lannister.java"); Path stark = Paths.get("Stark.java"); Path targaryen = Paths.get("Targaryen.java"); ImmutableList<Path> input = ImmutableList.of(baratheon, lannister, stark, targaryen); for (Path p : input) { if (!p.equals(baratheon)) { filesystem.touch(p); } } try { coercer.coerce(buildRuleResolver, filesystem, Paths.get(""), input); } catch (CoerceFailedException e) { String result = e.getMessage(); String expected = "cannot coerce 'Baratheon.java'"; for (Path p : input) { if (!p.equals(baratheon)) { assertFalse(result.contains(p.toString())); } } assertTrue(result.contains(expected)); } }
@Test public void coercePath() throws CoerceFailedException, IOException { String path = "hello.a"; projectFilesystem.touch(Paths.get(path)); SourcePath sourcePath = sourcePathTypeCoercer.coerce(cellRoots, projectFilesystem, pathRelativeToProjectRoot, path); assertEquals(new PathSourcePath(projectFilesystem, Paths.get(path)), sourcePath); }
@Override public Path createTempFile( Path directory, String prefix, String suffix, FileAttribute<?>... attrs) throws IOException { Path path; do { String str = new BigInteger(130, RANDOM).toString(32); path = directory.resolve(prefix + str + suffix); } while (exists(path)); touch(path); return path; }
@Test public void coercingAbsolutePathThrows() throws CoerceFailedException, IOException { Path path = MorePathsForTests.rootRelativePath("hello.a"); projectFilesystem.touch(path); exception.expect(CoerceFailedException.class); exception.expectMessage("SourcePath cannot contain an absolute path"); sourcePathTypeCoercer.coerce( cellRoots, projectFilesystem, pathRelativeToProjectRoot, path.toString()); }
@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()); }
@Test public void createLexYaccBuildRules() throws IOException { BuildRuleResolver resolver = new BuildRuleResolver(); // Setup our C++ buck config with the paths to the lex/yacc binaries. FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); Path lexPath = Paths.get("lex"); filesystem.touch(lexPath); Path yaccPath = Paths.get("yacc"); filesystem.touch(yaccPath); BuckConfig buckConfig = FakeBuckConfig.builder() .setSections( ImmutableMap.of( "cxx", ImmutableMap.of( "lex", lexPath.toString(), "yacc", yaccPath.toString()))) .setFilesystem(filesystem) .build(); CxxPlatform cxxBuckConfig = DefaultCxxPlatforms.build(new CxxBuckConfig(buckConfig)); // Setup the target name and build params. UnflavoredBuildTarget target = BuildTargetFactory.newInstance("//:test").getUnflavoredBuildTarget(); BuildRuleParams params = new FakeBuildRuleParamsBuilder(BuildTarget.of(target)).build(); // Setup a genrule that generates our lex source. String lexSourceName = "test.ll"; BuildTarget genruleTarget = BuildTargetFactory.newInstance("//:genrule_lex"); Genrule genrule = (Genrule) GenruleBuilder.newGenruleBuilder(genruleTarget).setOut(lexSourceName).build(resolver); SourcePath lexSource = new BuildTargetSourcePath(genrule.getBuildTarget()); // Use a regular path for our yacc source. String yaccSourceName = "test.yy"; SourcePath yaccSource = new TestSourcePath(yaccSourceName); // Build the rules. CxxHeaderSourceSpec actual = CxxDescriptionEnhancer.createLexYaccBuildRules( params, resolver, cxxBuckConfig, ImmutableList.<String>of(), ImmutableMap.of(lexSourceName, lexSource), ImmutableList.<String>of(), ImmutableMap.of(yaccSourceName, yaccSource)); // Grab the generated lex rule and verify it has the genrule as a dep. Lex lex = (Lex) resolver.getRule(CxxDescriptionEnhancer.createLexBuildTarget(target, lexSourceName)); assertNotNull(lex); assertEquals(ImmutableSortedSet.<BuildRule>of(genrule), lex.getDeps()); // Grab the generated yacc rule and verify it has no deps. Yacc yacc = (Yacc) resolver.getRule(CxxDescriptionEnhancer.createYaccBuildTarget(target, yaccSourceName)); assertNotNull(yacc); assertEquals(ImmutableSortedSet.<BuildRule>of(), yacc.getDeps()); // Check the header/source spec is correct. Path lexOutputSource = CxxDescriptionEnhancer.getLexSourceOutputPath(target, lexSourceName); Path lexOutputHeader = CxxDescriptionEnhancer.getLexHeaderOutputPath(target, lexSourceName); Path yaccOutputPrefix = CxxDescriptionEnhancer.getYaccOutputPrefix( target, Files.getNameWithoutExtension(yaccSourceName)); Path yaccOutputSource = Yacc.getSourceOutputPath(yaccOutputPrefix); Path yaccOutputHeader = Yacc.getHeaderOutputPath(yaccOutputPrefix); CxxHeaderSourceSpec expected = CxxHeaderSourceSpec.of( ImmutableMap.<Path, SourcePath>of( target.getBasePath().resolve(lexSourceName + ".h"), new BuildTargetSourcePath(lex.getBuildTarget(), lexOutputHeader), target.getBasePath().resolve(yaccSourceName + ".h"), new BuildTargetSourcePath(yacc.getBuildTarget(), yaccOutputHeader)), ImmutableMap.of( lexSourceName + ".cc", CxxSource.of( CxxSource.Type.CXX, new BuildTargetSourcePath(lex.getBuildTarget(), lexOutputSource), ImmutableList.<String>of()), yaccSourceName + ".cc", CxxSource.of( CxxSource.Type.CXX, new BuildTargetSourcePath(yacc.getBuildTarget(), yaccOutputSource), ImmutableList.<String>of()))); assertEquals(expected, actual); }