| // Copyright 2020 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.rules.cpp; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static org.junit.Assert.assertThrows; |
| |
| import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; |
| import java.io.IOException; |
| import net.starlark.java.eval.NoneType; |
| import net.starlark.java.eval.Sequence; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** Tests for C++ fragments in Starlark. */ |
| @RunWith(JUnit4.class) |
| public final class CppConfigurationStarlarkTest extends BuildViewTestCase { |
| |
| @Test |
| public void testMinimumOsVersion() throws Exception { |
| useConfiguration("--minimum_os_version=-wololoo"); |
| writeRuleReturning("ctx.fragments.cpp.minimum_os_version()"); |
| |
| String result = (String) getConfiguredTarget("//foo:bar").get("result"); |
| assertThat(result).isEqualTo("-wololoo"); |
| } |
| |
| @Test |
| public void testNullMinimumOsVersion() throws Exception { |
| writeRuleReturning("ctx.fragments.cpp.minimum_os_version()"); |
| |
| Object result = getConfiguredTarget("//foo:bar").get("result"); |
| assertThat(result).isInstanceOf(NoneType.class); |
| } |
| |
| @Test |
| public void testCopts() throws Exception { |
| writeRuleReturning("ctx.fragments.cpp.copts"); |
| useConfiguration("--copt=-wololoo"); |
| |
| @SuppressWarnings("unchecked") |
| Sequence<String> result = (Sequence<String>) getConfiguredTarget("//foo:bar").get("result"); |
| assertThat(result).containsExactly("-wololoo"); |
| } |
| |
| @Test |
| public void testCxxopts() throws Exception { |
| writeRuleReturning("ctx.fragments.cpp.cxxopts"); |
| useConfiguration("--cxxopt=-wololoo"); |
| |
| @SuppressWarnings("unchecked") |
| Sequence<String> result = (Sequence<String>) getConfiguredTarget("//foo:bar").get("result"); |
| assertThat(result).containsExactly("-wololoo"); |
| } |
| |
| @Test |
| public void testConlyopts() throws Exception { |
| writeRuleReturning("ctx.fragments.cpp.conlyopts"); |
| useConfiguration("--conlyopt=-wololoo"); |
| |
| @SuppressWarnings("unchecked") |
| Sequence<String> result = (Sequence<String>) getConfiguredTarget("//foo:bar").get("result"); |
| assertThat(result).containsExactly("-wololoo"); |
| } |
| |
| @Test |
| public void testObjcopts() throws Exception { |
| writeRuleReturning("ctx.fragments.cpp.objccopts"); |
| useConfiguration("--objccopt=-wololoo"); |
| |
| @SuppressWarnings("unchecked") |
| Sequence<String> result = (Sequence<String>) getConfiguredTarget("//foo:bar").get("result"); |
| assertThat(result).containsExactly("-wololoo"); |
| } |
| |
| @Test |
| public void testLinkopts() throws Exception { |
| writeRuleReturning("ctx.fragments.cpp.linkopts"); |
| useConfiguration("--linkopt=-wololoo"); |
| |
| @SuppressWarnings("unchecked") |
| Sequence<String> result = (Sequence<String>) getConfiguredTarget("//foo:bar").get("result"); |
| assertThat(result).containsExactly("-wololoo"); |
| } |
| |
| private static void assertBlockedFeature(AssertionError e, String feature) { |
| assertThat(e) |
| .hasMessageThat() |
| .contains( |
| String.format( |
| "cannot use private @_builtins API (feature '%s' in CppConfiguration)", feature)); |
| } |
| |
| @Test |
| public void testExpandedApiBlocked() throws Exception { |
| writeRuleReturning("foo", "pic.bzl", "pic", "ctx.fragments.cpp.force_pic()"); |
| writeRuleReturning("foo", "lcov.bzl", "lcov", "ctx.fragments.cpp.generate_llvm_lcov()"); |
| writeRuleReturning("foo", "fdo.bzl", "fdo", "ctx.fragments.cpp.fdo_instrument()"); |
| writeRuleReturning( |
| "foo", "hdr_deps.bzl", "hdr_deps", "ctx.fragments.cpp.process_headers_in_dependencies()"); |
| writeRuleReturning("foo", "save.bzl", "save", "ctx.fragments.cpp.save_feature_state()"); |
| writeRuleReturning( |
| "foo", |
| "fission.bzl", |
| "fission", |
| "ctx.fragments.cpp.fission_active_for_current_compilation_mode()"); |
| AssertionError e; |
| e = assertThrows(AssertionError.class, () -> getConfiguredTarget("//foo:pic")); |
| assertBlockedFeature(e, "force_pic"); |
| e = assertThrows(AssertionError.class, () -> getConfiguredTarget("//foo:lcov")); |
| assertBlockedFeature(e, "generate_llvm_lcov"); |
| e = assertThrows(AssertionError.class, () -> getConfiguredTarget("//foo:fdo")); |
| assertBlockedFeature(e, "fdo_instrument"); |
| e = assertThrows(AssertionError.class, () -> getConfiguredTarget("//foo:hdr_deps")); |
| assertThat(e).hasMessageThat().contains("cannot use private API"); |
| e = assertThrows(AssertionError.class, () -> getConfiguredTarget("//foo:save")); |
| assertThat(e).hasMessageThat().contains("cannot use private API"); |
| e = assertThrows(AssertionError.class, () -> getConfiguredTarget("//foo:fission")); |
| assertBlockedFeature(e, "fission_active_for_current_compilation_mode"); |
| } |
| |
| private void writeRuleReturning(String returns) throws IOException { |
| writeRuleReturning("foo", "lib.bzl", "bar", returns); |
| } |
| |
| private void writeRuleReturning(String path, String lib, String target, String returns) |
| throws IOException { |
| scratch.file( |
| path + "/" + lib, |
| "def _impl(ctx):", |
| " return struct(", |
| " result = " + returns, |
| " )", |
| "foo = rule(implementation=_impl, fragments = ['cpp'])"); |
| scratch.appendFile( |
| path + "/BUILD", "load(':" + lib + "', 'foo')", "foo(name='" + target + "')"); |
| } |
| } |