blob: 5fc605b92e85584c91bbf82acc59ee59415d6356 [file] [log] [blame]
/*
* 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.thrift;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.python.PythonLibrary;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleParamsFactory;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.FakeBuildRule;
import com.facebook.buck.rules.FakeBuildRuleParamsBuilder;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.TestSourcePath;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import org.junit.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
public class ThriftPythonEnhancerTest {
private static final BuildTarget TARGET = BuildTargetFactory.newInstance("//:test#python");
private static final FakeBuckConfig BUCK_CONFIG = new FakeBuckConfig();
private static final ThriftBuckConfig THRIFT_BUCK_CONFIG = new ThriftBuckConfig(BUCK_CONFIG);
private static final ThriftPythonEnhancer ENHANCER = new ThriftPythonEnhancer(
THRIFT_BUCK_CONFIG,
ThriftPythonEnhancer.Type.NORMAL);
private static final ThriftPythonEnhancer TWISTED_ENHANCER = new ThriftPythonEnhancer(
THRIFT_BUCK_CONFIG,
ThriftPythonEnhancer.Type.TWISTED);
private static FakeBuildRule createFakeBuildRule(
String target,
SourcePathResolver resolver,
BuildRule... deps) {
return new FakeBuildRule(
new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance(target))
.setDeps(ImmutableSortedSet.copyOf(deps))
.build(),
resolver);
}
private static ThriftCompiler createFakeThriftCompiler(
String target,
SourcePathResolver resolver) {
return new ThriftCompiler(
BuildRuleParamsFactory.createTrivialBuildRuleParams(
BuildTargetFactory.newInstance(target)),
resolver,
new TestSourcePath("compiler"),
ImmutableList.<String>of(),
Paths.get("output"),
new TestSourcePath("source"),
"language",
ImmutableSet.<String>of(),
ImmutableList.<Path>of(),
ImmutableMap.<Path, SourcePath>of());
}
@Test
public void getLanguage() {
assertEquals(
"py",
ENHANCER.getLanguage());
}
@Test
public void getFlavor() {
assertEquals(
ImmutableFlavor.of("py"),
ENHANCER.getFlavor());
}
private ImmutableSet<String> addTwisted(ImmutableSet<String> options) {
return ImmutableSet.<String>builder()
.add("twisted")
.addAll(options)
.build();
}
@Test
public void getOptions() {
ThriftConstructorArg arg = new ThriftConstructorArg();
ImmutableSet<String> options;
// Test empty options.
options = ImmutableSet.of();
arg.pyOptions = Optional.of(options);
assertEquals(
options,
ENHANCER.getOptions(TARGET, arg));
assertEquals(
addTwisted(options),
TWISTED_ENHANCER.getOptions(TARGET, arg));
// Test set options.
options = ImmutableSet.of("test", "option");
arg.pyOptions = Optional.of(options);
assertEquals(
options,
ENHANCER.getOptions(TARGET, arg));
assertEquals(
addTwisted(options),
TWISTED_ENHANCER.getOptions(TARGET, arg));
// Test absent options.
arg.pyOptions = Optional.absent();
assertEquals(
ImmutableSet.<String>of(),
ENHANCER.getOptions(TARGET, arg));
assertEquals(
addTwisted(ImmutableSet.<String>of()),
TWISTED_ENHANCER.getOptions(TARGET, arg));
}
private void expectImplicitDeps(
ThriftPythonEnhancer enhancer,
ImmutableSet<String> options,
ImmutableSet<BuildTarget> expected) {
ThriftConstructorArg arg = new ThriftConstructorArg();
arg.pyOptions = Optional.of(options);
assertEquals(
expected,
enhancer.getImplicitDepsForTargetFromConstructorArg(TARGET, arg));
}
@Test
public void getImplicitDeps() {
// Setup enhancers which set all appropriate values in the config.
ImmutableMap<String, BuildTarget> config = ImmutableMap.of(
"python_library", BuildTargetFactory.newInstance("//:python_library"),
"python_twisted_library", BuildTargetFactory.newInstance("//:python_twisted_library"));
ImmutableMap.Builder<String, String> strConfig = ImmutableMap.builder();
for (ImmutableMap.Entry<String, BuildTarget> ent : config.entrySet()) {
strConfig.put(ent.getKey(), ent.getValue().toString());
}
FakeBuckConfig buckConfig = new FakeBuckConfig(
ImmutableMap.<String, Map<String, String>>of("thrift", strConfig.build()));
ThriftBuckConfig thriftBuckConfig = new ThriftBuckConfig(buckConfig);
ThriftPythonEnhancer enhancer = new ThriftPythonEnhancer(
thriftBuckConfig,
ThriftPythonEnhancer.Type.NORMAL);
ThriftPythonEnhancer twistedEnhancer = new ThriftPythonEnhancer(
thriftBuckConfig,
ThriftPythonEnhancer.Type.TWISTED);
// With no options we just need to find the python thrift library.
expectImplicitDeps(
enhancer,
ImmutableSet.<String>of(),
ImmutableSet.of(
config.get("python_library")));
// With the twisted enhancer option we also expect the twisted library.
expectImplicitDeps(
twistedEnhancer,
ImmutableSet.of("twisted"),
ImmutableSet.of(
config.get("python_library"),
config.get("python_twisted_library")));
}
@Test
public void createBuildRule() {
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
BuildRuleParams flavoredParams =
BuildRuleParamsFactory.createTrivialBuildRuleParams(TARGET);
// Add a dummy dependency to the constructor arg to make sure it gets through.
ThriftConstructorArg arg = new ThriftConstructorArg();
arg.pyOptions = Optional.absent();
arg.pyBaseModule = Optional.absent();
// Setup up some thrift inputs to pass to the createBuildRule method.
ImmutableMap<String, ThriftSource> sources = ImmutableMap.of(
"test1.thrift", new ThriftSource(
createFakeThriftCompiler("//:thrift_source1", pathResolver),
ImmutableList.<String>of(),
Paths.get("output1")),
"test2.thrift", new ThriftSource(
createFakeThriftCompiler("//:thrift_source2", pathResolver),
ImmutableList.<String>of(),
Paths.get("output2")));
// Create a dummy implicit dep to pass in.
ImmutableSortedSet<BuildRule> deps = ImmutableSortedSet.<BuildRule>of(
createFakeBuildRule("//:dep", pathResolver));
// Run the enhancer to create the language specific build rule.
PythonLibrary library = ENHANCER.createBuildRule(
flavoredParams,
resolver,
arg,
sources,
deps);
// Verify that the top-level default python lib has correct deps.
assertEquals(deps, library.getDeps());
}
@Test
public void baseModule() {
BuildTarget target = BuildTargetFactory.newInstance("//test:test");
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
BuildRuleParams flavoredParams =
BuildRuleParamsFactory.createTrivialBuildRuleParams(target);
// Add a dummy dependency to the constructor arg to make sure it gets through.
ThriftConstructorArg arg = new ThriftConstructorArg();
arg.pyOptions = Optional.absent();
// Setup up some thrift inputs to pass to the createBuildRule method.
ImmutableMap<String, ThriftSource> sources = ImmutableMap.of(
"test.thrift", new ThriftSource(
createFakeThriftCompiler("//:thrift_source", pathResolver),
ImmutableList.<String>of(),
Paths.get("output")));
// Verify that not setting the base module parameter defaults to the build target base path.
arg.pyBaseModule = Optional.absent();
PythonLibrary normal = ENHANCER.createBuildRule(
flavoredParams,
resolver,
arg,
sources,
ImmutableSortedSet.<BuildRule>of());
for (ImmutableMap.Entry<Path, SourcePath> ent : normal.getSrcs().entrySet()) {
assertTrue(ent.getKey().toString(), ent.getKey().startsWith(target.getBasePath()));
}
// Verify that setting the base module uses it correctly.
arg.pyBaseModule = Optional.of("blah");
PythonLibrary baseModule = ENHANCER.createBuildRule(
flavoredParams,
resolver,
arg,
sources,
ImmutableSortedSet.<BuildRule>of());
for (ImmutableMap.Entry<Path, SourcePath> ent : baseModule.getSrcs().entrySet()) {
assertTrue(ent.getKey().startsWith(Paths.get(arg.pyBaseModule.get())));
}
}
}