diff options
author | 2015-04-17 13:16:51 +0000 | |
---|---|---|
committer | 2015-04-17 15:42:49 +0000 | |
commit | d87465e66cd282c99496dc68cf94f7de5f04ab90 (patch) | |
tree | 4c8640846dc03b62f9174998c147143e9c41f6dd /src | |
parent | 8b5cb2e076378572219cabdb088e8dddd679d0a0 (diff) |
Open source the configuration tests.
- update the MOCK_CROSSTOOL to provide more stuff needed by tests
- add a THIS_IS_BAZEL constant to allow disabling individual test cases
- disable some tests in Bazel
The disabled tests are mainly due to differences in the test setup - making
the test setups more similar will largely fix that. I think we'll make some
changes to our internal setup, too, not just the external one. For example,
the use of 'k8' and 'piii' to refer to 'x86_64' and 'x86' seems archaic.
I decided to leave the dependency on the C++ and Java configurations rather
than rewriting the tests to use mock configurations. That would be nicer, but
also requires significantly more work.
--
MOS_MIGRATED_REVID=91399406
Diffstat (limited to 'src')
11 files changed, 891 insertions, 102 deletions
diff --git a/src/test/java/BUILD b/src/test/java/BUILD index 8cb595f069..79043b5f3c 100644 --- a/src/test/java/BUILD +++ b/src/test/java/BUILD @@ -195,6 +195,7 @@ java_library( "com/google/devtools/build/lib/exec/util/*.java", "com/google/devtools/build/lib/packages/util/*.java", "com/google/devtools/build/lib/skyframe/util/*.java", + "com/google/devtools/build/lib/analysis/BazelAnalysisMock.java", ]), data = [ "//src/main/native:libunix.dylib", @@ -223,7 +224,29 @@ java_test( name = "analysis_actions_test", srcs = glob([ "com/google/devtools/build/lib/analysis/actions/*.java", - "com/google/devtools/build/lib/analysis/BazelAnalysisMock.java", + ]), + args = ["com.google.devtools.build.lib.AllTests"], + deps = [ + ":actions_testutil", + ":analysis_testutil", + ":foundations_testutil", + ":test_runner", + ":testutil", + "//src/main/java:bazel-core", + "//src/main/protobuf:proto_extra_actions_base", + "//third_party:guava", + "//third_party:guava-testlib", + "//third_party:jsr305", + "//third_party:junit4", + "//third_party:mockito", + "//third_party:truth", + ], +) + +java_test( + name = "analysis_config_test", + srcs = glob([ + "com/google/devtools/build/lib/analysis/config/*.java", ]), args = ["com.google.devtools.build.lib.AllTests"], deps = [ diff --git a/src/test/java/MOCK_CROSSTOOL b/src/test/java/MOCK_CROSSTOOL index c57df53309..29f1a28b91 100644 --- a/src/test/java/MOCK_CROSSTOOL +++ b/src/test/java/MOCK_CROSSTOOL @@ -1,13 +1,20 @@ -# This test resource file needs to cover all the things that we expect in the -# tests. While it currently looks like a verbatim copy of tools/cpp/CROSSTOOL, -# that's just because not all tests are there yet. +# This test resource file is the default test setup - it largely matches what +# we have in our repository cover; individual test cases can override this in +# order to test more scenarios. -major_version: "local" -minor_version: "" +major_version: "1" +minor_version: "42" default_target_cpu: "k8" + +# TODO(bazel-team): We should change these identifiers to match what everyone +# else is using, but that requires rewriting a lot of our tests. default_toolchain { cpu: "k8" - toolchain_identifier: "local_linux" + toolchain_identifier: "k8" +} +default_toolchain { + cpu: "piii" + toolchain_identifier: "piii" } default_toolchain { cpu: "darwin" @@ -15,65 +22,100 @@ default_toolchain { } toolchain { - abi_version: "local" - abi_libc_version: "local" - builtin_sysroot: "" - compiler: "compiler" + toolchain_identifier: "k8" + host_system_name: "local" - needsPic: true - supports_gold_linker: false - supports_incremental_linker: false - supports_fission: false - supports_interface_shared_objects: false - supports_normalizing_ar: false - supports_start_end_lib: false - supports_thin_archives: false - target_libc: "local" - target_cpu: "local" target_system_name: "local" - toolchain_identifier: "local_linux" + target_cpu: "k8" + target_libc: "local" + compiler: "compiler" + + abi_version: "local" + abi_libc_version: "local" tool_path { name: "ar" path: "/usr/bin/ar" } tool_path { name: "compat-ld" path: "/usr/bin/ld" } tool_path { name: "cpp" path: "/usr/bin/cpp" } tool_path { name: "dwp" path: "/usr/bin/dwp" } tool_path { name: "gcc" path: "/usr/bin/gcc" } + tool_path { name: "gcov" path: "/usr/bin/gcov" } + tool_path { name: "ld" path: "/usr/bin/ld" } + tool_path { name: "nm" path: "/usr/bin/nm" } + tool_path { name: "objcopy" path: "/usr/bin/objcopy" } + tool_path { name: "objdump" path: "/usr/bin/objdump" } + tool_path { name: "strip" path: "/usr/bin/strip" } + + builtin_sysroot: "" cxx_flag: "-std=c++0x" linker_flag: "-lstdc++" - # TODO(bazel-team): In theory, the path here ought to exactly match the path - # used by gcc. That works because bazel currently doesn't track files at - # absolute locations and has no remote execution, yet. However, this will need - # to be fixed, maybe with auto-detection? cxx_builtin_include_directory: "/usr/lib/gcc/" cxx_builtin_include_directory: "/usr/local/include" cxx_builtin_include_directory: "/usr/include" + objcopy_embed_flag: "-I" + objcopy_embed_flag: "binary" +} + +toolchain { + toolchain_identifier: "piii" + + host_system_name: "local" + target_system_name: "local" + target_cpu: "piii" + target_libc: "local" + compiler: "compiler" + + abi_version: "local" + abi_libc_version: "local" + + tool_path { name: "ar" path: "/usr/bin/ar" } + tool_path { name: "compat-ld" path: "/usr/bin/ld" } + tool_path { name: "cpp" path: "/usr/bin/cpp" } + tool_path { name: "dwp" path: "/usr/bin/dwp" } + tool_path { name: "gcc" path: "/usr/bin/gcc" } tool_path { name: "gcov" path: "/usr/bin/gcov" } tool_path { name: "ld" path: "/usr/bin/ld" } tool_path { name: "nm" path: "/usr/bin/nm" } tool_path { name: "objcopy" path: "/usr/bin/objcopy" } - objcopy_embed_flag: "-I" - objcopy_embed_flag: "binary" tool_path { name: "objdump" path: "/usr/bin/objdump" } tool_path { name: "strip" path: "/usr/bin/strip" } + + builtin_sysroot: "" + cxx_flag: "-std=c++0x" + linker_flag: "-lstdc++" + cxx_builtin_include_directory: "/usr/lib/gcc/" + cxx_builtin_include_directory: "/usr/local/include" + cxx_builtin_include_directory: "/usr/include" + objcopy_embed_flag: "-I" + objcopy_embed_flag: "binary" } toolchain { - abi_version: "local" - abi_libc_version: "local" - builtin_sysroot: "" - compiler: "compiler" + toolchain_identifier: "local_darwin" + host_system_name: "local" - needsPic: true - target_libc: "macosx" - target_cpu: "darwin" target_system_name: "local" - toolchain_identifier: "local_darwin" + target_cpu: "darwin" + target_libc: "macosx" + compiler: "compiler" + + abi_version: "local" + abi_libc_version: "local" tool_path { name: "ar" path: "/usr/bin/libtool" } tool_path { name: "compat-ld" path: "/usr/bin/ld" } tool_path { name: "cpp" path: "/usr/bin/cpp" } tool_path { name: "dwp" path: "/usr/bin/dwp" } tool_path { name: "gcc" path: "/usr/bin/gcc" } + tool_path { name: "gcov" path: "/usr/bin/gcov" } + tool_path { name: "ld" path: "/usr/bin/ld" } + tool_path { name: "nm" path: "/usr/bin/nm" } + tool_path { name: "objcopy" path: "/usr/bin/objcopy" } + tool_path { name: "objdump" path: "/usr/bin/objdump" } + tool_path { name: "strip" path: "/usr/bin/strip" } + + needsPic: true + + builtin_sysroot: "" cxx_flag: "-std=c++0x" ar_flag: "-static" ar_flag: "-s" @@ -84,114 +126,102 @@ toolchain { cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs" cxx_builtin_include_directory: "/opt/local/include" cxx_builtin_include_directory: "/Library/Developer/CommandLineTools" - tool_path { name: "gcov" path: "/usr/bin/gcov" } - tool_path { name: "ld" path: "/usr/bin/ld" } - tool_path { name: "nm" path: "/usr/bin/nm" } - tool_path { name: "objcopy" path: "/usr/bin/objcopy" } objcopy_embed_flag: "-I" objcopy_embed_flag: "binary" - tool_path { name: "objdump" path: "/usr/bin/objdump" } - tool_path { name: "strip" path: "/usr/bin/strip" } } toolchain { - abi_version: "local" - abi_libc_version: "local" - builtin_sysroot: "" - compiler: "windows_mingw" + toolchain_identifier: "local_windows_mingw" + host_system_name: "local" - needsPic: false - target_libc: "local" - target_cpu: "k8" target_system_name: "local" - toolchain_identifier: "local_windows_mingw" + target_cpu: "k8" + target_libc: "local" + compiler: "windows_mingw" + + abi_version: "local" + abi_libc_version: "local" tool_path { name: "ar" path: "C:/mingw/bin/ar" } tool_path { name: "compat-ld" path: "C:/mingw/bin/ld" } tool_path { name: "cpp" path: "C:/mingw/bin/cpp" } tool_path { name: "dwp" path: "C:/mingw/bin/dwp" } tool_path { name: "gcc" path: "C:/mingw/bin/gcc" } - cxx_flag: "-std=c++0x" - # TODO(bazel-team): In theory, the path here ought to exactly match the path - # used by gcc. That works because bazel currently doesn't track files at - # absolute locations and has no remote execution, yet. However, this will need - # to be fixed, maybe with auto-detection? - cxx_builtin_include_directory: "C:/mingw/include" - cxx_builtin_include_directory: "C:/mingw/lib/gcc" tool_path { name: "gcov" path: "C:/mingw/bin/gcov" } tool_path { name: "ld" path: "C:/mingw/bin/ld" } tool_path { name: "nm" path: "C:/mingw/bin/nm" } tool_path { name: "objcopy" path: "C:/mingw/bin/objcopy" } - objcopy_embed_flag: "-I" - objcopy_embed_flag: "binary" tool_path { name: "objdump" path: "C:/mingw/bin/objdump" } tool_path { name: "strip" path: "C:/mingw/bin/strip" } + + builtin_sysroot: "" + cxx_flag: "-std=c++0x" + cxx_builtin_include_directory: "C:/mingw/include" + cxx_builtin_include_directory: "C:/mingw/lib/gcc" + objcopy_embed_flag: "-I" + objcopy_embed_flag: "binary" } toolchain { - abi_version: "local" - abi_libc_version: "local" - builtin_sysroot: "" - compiler: "windows_msys64_mingw64" + toolchain_identifier: "local_windows_msys64_mingw64" + host_system_name: "local" - needsPic: false - target_libc: "local" - target_cpu: "k8" target_system_name: "local" - toolchain_identifier: "local_windows_msys64_mingw64" + target_cpu: "k8" + target_libc: "local" + compiler: "windows_msys64_mingw64" + + abi_version: "local" + abi_libc_version: "local" tool_path { name: "ar" path: "C:/msys64/mingw64/bin/ar" } tool_path { name: "compat-ld" path: "C:/msys64/mingw64/bin/ld" } tool_path { name: "cpp" path: "C:/msys64/mingw64/bin/cpp" } tool_path { name: "dwp" path: "C:/msys64/mingw64/bin/dwp" } tool_path { name: "gcc" path: "C:/msys64/mingw64/bin/gcc" } - cxx_flag: "-std=c++0x" - # TODO(bazel-team): In theory, the path here ought to exactly match the path - # used by gcc. That works because bazel currently doesn't track files at - # absolute locations and has no remote execution, yet. However, this will need - # to be fixed, maybe with auto-detection? - cxx_builtin_include_directory: "C:/msys64/mingw64/x86_64-w64-mingw32/include" tool_path { name: "gcov" path: "C:/msys64/mingw64/bin/gcov" } tool_path { name: "ld" path: "C:/msys64/mingw64/bin/ld" } tool_path { name: "nm" path: "C:/msys64/mingw64/bin/nm" } tool_path { name: "objcopy" path: "C:/msys64/mingw64/bin/objcopy" } - objcopy_embed_flag: "-I" - objcopy_embed_flag: "binary" tool_path { name: "objdump" path: "C:/msys64/mingw64/bin/objdump" } tool_path { name: "strip" path: "C:/msys64/mingw64/bin/strip" } + + builtin_sysroot: "" + cxx_flag: "-std=c++0x" + cxx_builtin_include_directory: "C:/msys64/mingw64/x86_64-w64-mingw32/include" + objcopy_embed_flag: "-I" + objcopy_embed_flag: "binary" } toolchain { - abi_version: "local" - abi_libc_version: "local" - builtin_sysroot: "" - compiler: "windows_clang" + toolchain_identifier: "local_windows_clang" + host_system_name: "local" - needsPic: false - target_libc: "local" - target_cpu: "k8" target_system_name: "local" - toolchain_identifier: "local_windows_clang" + target_cpu: "k8" + target_libc: "local" + compiler: "windows_clang" + + abi_version: "local" + abi_libc_version: "local" tool_path { name: "ar" path: "C:/mingw/bin/ar" } tool_path { name: "compat-ld" path: "C:/Program Files (x86)/LLVM/bin/ld" } tool_path { name: "cpp" path: "C:/Program Files (x86)/LLVM/bin/cpp" } tool_path { name: "dwp" path: "C:/Program Files (x86)/LLVM/bin/dwp" } tool_path { name: "gcc" path: "C:/Program Files (x86)/LLVM/bin/clang" } - cxx_flag: "-std=c++0x" - # TODO(bazel-team): In theory, the path here ought to exactly match the path - # used by gcc. That works because bazel currently doesn't track files at - # absolute locations and has no remote execution, yet. However, this will need - # to be fixed, maybe with auto-detection? - cxx_builtin_include_directory: "/usr/lib/gcc/" - cxx_builtin_include_directory: "/usr/local/include" - cxx_builtin_include_directory: "/usr/include" tool_path { name: "gcov" path: "C:/Program Files (x86)/LLVM/bin/gcov" } tool_path { name: "ld" path: "C:/Program Files (x86)/LLVM/bin/ld" } tool_path { name: "nm" path: "C:/Program Files (x86)/LLVM/bin/nm" } tool_path { name: "objcopy" path: "C:/Program Files (x86)/LLVM/bin/objcopy" } - objcopy_embed_flag: "-I" - objcopy_embed_flag: "binary" tool_path { name: "objdump" path: "C:/Program Files (x86)/LLVM/bin/objdump" } tool_path { name: "strip" path: "C:/Program Files (x86)/LLVM/bin/strip" } + + cxx_flag: "-std=c++0x" + cxx_builtin_include_directory: "/usr/lib/gcc/" + cxx_builtin_include_directory: "/usr/local/include" + cxx_builtin_include_directory: "/usr/include" + objcopy_embed_flag: "-I" + objcopy_embed_flag: "binary" + builtin_sysroot: "" } diff --git a/src/test/java/com/google/devtools/build/lib/analysis/BazelAnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/BazelAnalysisMock.java index 6107b4180b..b428a2ad6a 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/BazelAnalysisMock.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/BazelAnalysisMock.java @@ -55,15 +55,22 @@ public class BazelAnalysisMock extends AnalysisMock { " 'JavaBuilderCanary_deploy.jar', 'ijar'])"); config.create("tools/cpp/BUILD", "filegroup(name = 'toolchain', srcs = [':cc-compiler-local', ':empty'])", - "cc_toolchain(name = 'cc-compiler-local', all_files = ':empty', compiler_files = ':empty',", - "cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ", - " linker_files = ':empty',", - "objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',)", + "cc_toolchain(name = 'cc-compiler-k8', all_files = ':empty', compiler_files = ':empty',", + " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ", + " linker_files = ':empty',", + " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',", + ")", + "cc_toolchain(name = 'cc-compiler-piii', all_files = ':empty', compiler_files = ':empty',", + " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ", + " linker_files = ':empty',", + " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',", + ")", "cc_toolchain(name = 'cc-compiler-darwin', all_files = ':empty', ", - " compiler_files = ':empty',", - "cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ", - " linker_files = ':empty',", - "objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',)"); + " compiler_files = ':empty',", + " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ", + " linker_files = ':empty',", + " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',", + ")"); config.create("tools/cpp/CROSSTOOL", readFromResources("MOCK_CROSSTOOL")); } @@ -105,6 +112,6 @@ public class BazelAnalysisMock extends AnalysisMock { @Override public ImmutableList<Class<? extends FragmentOptions>> getBuildOptions() { - throw new UnsupportedOperationException(); + return BazelRuleClassProvider.BUILD_OPTIONS; } } diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java new file mode 100644 index 0000000000..8089f5dc8d --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java @@ -0,0 +1,304 @@ +// Copyright 2006-2015 Google Inc. 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.analysis.config; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment; +import com.google.devtools.build.lib.analysis.util.ConfigurationTestCase; +import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition; +import com.google.devtools.build.lib.rules.cpp.CppConfiguration; +import com.google.devtools.build.lib.rules.cpp.CppOptions; +import com.google.devtools.build.lib.rules.java.JavaConfiguration; +import com.google.devtools.build.lib.syntax.Label; +import com.google.devtools.build.lib.testutil.TestConstants; +import com.google.devtools.build.lib.testutil.TestUtils; +import com.google.devtools.build.lib.vfs.FileSystem; +import com.google.devtools.build.lib.vfs.Path; +import com.google.devtools.common.options.Options; + +import java.util.Map; + +/** + * Tests for {@link BuildConfiguration}. + */ +public class BuildConfigurationTest extends ConfigurationTestCase { + + public void testBasics() throws Exception { + if (TestConstants.THIS_IS_BAZEL) { + return; + } + + BuildConfiguration config = create("--cpu=piii"); + String outputDirPrefix = outputBase + + "/workspace/blaze-out/gcc-4.4.0-glibc-2.3.6-grte-piii-fastbuild"; + + assertEquals(outputDirPrefix, + config.getOutputDirectory().getPath().toString()); + assertEquals(outputDirPrefix + "/bin", + config.getBinDirectory().getPath().toString()); + assertEquals(outputDirPrefix + "/include", + config.getIncludeDirectory().getPath().toString()); + assertEquals(outputDirPrefix + "/genfiles", + config.getGenfilesDirectory().getPath().toString()); + assertEquals(outputDirPrefix + "/testlogs", + config.getTestLogsDirectory().getPath().toString()); + } + + public void testPlatformSuffix() throws Exception { + if (TestConstants.THIS_IS_BAZEL) { + return; + } + + BuildConfiguration config = create("--platform_suffix=-test"); + assertEquals("gcc-4.4.0-glibc-2.3.6-grte-k8-fastbuild-test", + config.getShortName()); + assertEquals(outputBase + "/workspace/blaze-out/gcc-4.4.0-glibc-2.3.6-grte-k8-fastbuild-test", + config.getOutputDirectory().getPath().toString()); + } + + public void testEnvironment() throws Exception { + if (TestConstants.THIS_IS_BAZEL) { + return; + } + + Map<String, String> env = create().getDefaultShellEnvironment(); + assertThat(env).containsEntry("LANG", "en_US"); + assertThat(env).containsKey("PATH"); + assertThat(env.get("PATH")).contains("/bin:/usr/bin"); + try { + env.put("FOO", "bar"); + fail("modifiable default environment"); + } catch (UnsupportedOperationException ignored) { + //expected exception + } + } + + public void testHostCpu() throws Exception { + for (String cpu : new String[] { "piii", "k8" }) { + BuildConfiguration hostConfig = createHost("--host_cpu=" + cpu); + assertEquals(cpu, hostConfig.getFragment(CppConfiguration.class).getTargetCpu()); + } + } + + public void testHostCrosstoolTop() throws Exception { + if (TestConstants.THIS_IS_BAZEL) { + return; + } + + BuildConfiguration config = create("--cpu=piii"); + assertEquals(Label.parseAbsoluteUnchecked("//third_party/crosstool/mock:cc-compiler-piii"), + config.getFragment(CppConfiguration.class).getCcToolchainRuleLabel()); + + BuildConfiguration hostConfig = config.getConfiguration(ConfigurationTransition.HOST); + assertEquals(Label.parseAbsoluteUnchecked("//third_party/crosstool/mock:cc-compiler-k8"), + hostConfig.getFragment(CppConfiguration.class).getCcToolchainRuleLabel()); + } + + public void testTestEnvironment() throws Exception { + clientEnv.put("MY_VAR1", "1"); + clientEnv.put("MY_VAR2", "1"); + BuildConfiguration config = create( + "--test_env=MY_VAR1", "--test_env=MY_VAR2=2", + "--test_env=MY_VAR3=3", "--test_env=NO_SUCH_VAR"); + assertThat(config.getTestEnv()).containsEntry("MY_VAR1", "1"); + assertThat(config.getTestEnv()).containsEntry("MY_VAR2", "2"); + assertThat(config.getTestEnv()).containsEntry("MY_VAR3", "3"); + assertThat(config.getTestEnv()).doesNotContainKey("NO_SUCH_VAR"); + } + + public void testMakeEnvFlags() throws Exception { + BuildConfiguration config = create(); + assertThat(config.getMakeEnvironment().get("STRIP")).contains("strip"); + } + + public void testCaching() throws Exception { + BuildConfiguration.Options a = Options.getDefaults(BuildConfiguration.Options.class); + BuildConfiguration.Options b = Options.getDefaults(BuildConfiguration.Options.class); + // The String representations of the BuildConfiguration.Options must be equal even if these are + // different objects, if they were created with the same options (no options in this case). + assertEquals(a.toString(), b.toString()); + assertEquals(a.cacheKey(), b.cacheKey()); + } + + private void checkInvalidCpuError(String cpuOption, String expectedMessage) throws Exception { + try { + create("--" + cpuOption + "=bogus"); + fail(); + } catch (InvalidConfigurationException e) { + assertThat(e).hasMessage(expectedMessage); + } + } + + public void testInvalidCpu() throws Exception { + checkInvalidCpuError("cpu", "No toolchain found for cpu 'bogus'"); + } + + public void testConfigurationsHaveUniqueOutputDirectories() throws Exception { + assertConfigurationsHaveUniqueOutputDirectories(createCollection()); + assertConfigurationsHaveUniqueOutputDirectories(createCollection("--compilation_mode=opt")); + } + + public void testMultiCpu() throws Exception { + if (TestConstants.THIS_IS_BAZEL) { + return; + } + + BuildConfigurationCollection master = createCollection( + "--multi_cpu=k8", "--multi_cpu=piii", "--ignore_java_and_python_cpu"); + assertThat(master.getTargetConfigurations()).hasSize(2); + // Note: the cpus are sorted alphabetically. + assertEquals("k8", master.getTargetConfigurations().get(0).getCpu()); + assertEquals("piii", master.getTargetConfigurations().get(1).getCpu()); + } + + /** + * Check that the cpus are sorted alphabetically regardless of the order in which they are + * specified. + */ + public void testMultiCpuSorting() throws Exception { + if (TestConstants.THIS_IS_BAZEL) { + return; + } + + for (int order = 0; order < 2; order++) { + BuildConfigurationCollection master; + if (order == 0) { + master = createCollection( + "--multi_cpu=k8", "--multi_cpu=piii", "--ignore_java_and_python_cpu"); + } else { + master = createCollection( + "--multi_cpu=piii", "--multi_cpu=k8", "--ignore_java_and_python_cpu"); + } + assertThat(master.getTargetConfigurations()).hasSize(2); + assertEquals("k8", master.getTargetConfigurations().get(0).getCpu()); + assertEquals("piii", master.getTargetConfigurations().get(1).getCpu()); + } + } + + public void testTargetEnvironment() throws Exception { + BuildConfiguration oneEnvConfig = create("--target_environment=//foo"); + assertThat(oneEnvConfig.getTargetEnvironments()).containsExactly(Label.parseAbsolute("//foo")); + + BuildConfiguration twoEnvsConfig = + create("--target_environment=//foo", "--target_environment=//bar"); + assertThat(twoEnvsConfig.getTargetEnvironments()) + .containsExactly(Label.parseAbsolute("//foo"), Label.parseAbsolute("//bar")); + + BuildConfiguration noEnvsConfig = create(); + assertThat(noEnvsConfig.getTargetEnvironments()).isEmpty(); + } + + @SafeVarargs + @SuppressWarnings("unchecked") + private final ConfigurationFragmentFactory createMockFragment( + final Class<? extends Fragment> creates, final Class<? extends Fragment>... dependsOn) { + return new ConfigurationFragmentFactory() { + + @Override + public Class<? extends Fragment> creates() { + return creates; + } + + @Override + public Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) + throws InvalidConfigurationException { + for (Class<? extends Fragment> fragmentType : dependsOn) { + env.getFragment(buildOptions, fragmentType); + } + return new Fragment() { + + @Override + public String getName() { + return creates.toString(); + } + + @Override + public String cacheKey() { + return creates.toString(); + } + }; + } + }; + } + + public void testCycleInFragments() throws Exception { + configurationFactory = new ConfigurationFactory( + getAnalysisMock().createConfigurationCollectionFactory(), + createMockFragment(CppConfiguration.class, JavaConfiguration.class), + createMockFragment(JavaConfiguration.class, CppConfiguration.class)); + try { + createCollection(); + fail(); + } catch (IllegalStateException e) { + // expected + } + } + + public void testMissingFragment() throws Exception { + configurationFactory = new ConfigurationFactory( + getAnalysisMock().createConfigurationCollectionFactory(), + createMockFragment(CppConfiguration.class, JavaConfiguration.class)); + try { + createCollection(); + fail(); + } catch (RuntimeException e) { + // expected + } + } + + public void testGlobalMakeVariableOverride() throws Exception { + assertThat(create().getMakeEnvironment()).containsEntry("COMPILATION_MODE", "fastbuild"); + BuildConfiguration config = create("--define", "COMPILATION_MODE=fluttershy"); + assertThat(config.getMakeEnvironment()).containsEntry("COMPILATION_MODE", "fluttershy"); + } + + public void testGetOptionClass() throws Exception { + BuildConfiguration config = create(); + // Directly defined option: + assertEquals(BuildConfiguration.Options.class, config.getOptionClass("compilation_mode")); + // Option defined in a fragment: + assertEquals(CppOptions.class, config.getOptionClass("lipo")); + // Unrecognized option: + assertNull(config.getOptionClass("do_my_laundry")); + } + + public void testGetOptionValue() throws Exception { + // Directly defined options: + assertEquals(CompilationMode.DBG, create("-c", "dbg").getOptionValue("compilation_mode")); + assertEquals(CompilationMode.OPT, create("-c", "opt").getOptionValue("compilation_mode")); + + // Options defined in a fragment: + assertEquals(Boolean.TRUE, create("--cc_include_scanning") + .getOptionValue("cc_include_scanning")); + assertEquals(Boolean.FALSE, create("--nocc_include_scanning") + .getOptionValue("cc_include_scanning")); + + // Unrecognized option: + assertNull(create().getOptionValue("do_my_dishes")); + + // Legitimately null option: + assertNull(create().getOptionValue("test_filter")); + } + + public void testSerialization() throws Exception { + FileSystem oldFileSystem = Path.getFileSystemForSerialization(); + try { + Path.setFileSystemForSerialization(scratchFS()); + TestUtils.serializeObject(createCollection()); + } finally { + Path.setFileSystemForSerialization(oldFileSystem); + } + } +} diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildOptionsTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildOptionsTest.java new file mode 100644 index 0000000000..10b8f685cd --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildOptionsTest.java @@ -0,0 +1,50 @@ +// Copyright 2009-2015 Google Inc. 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.analysis.config; + +import static org.junit.Assert.assertEquals; + +import com.google.common.collect.ImmutableList; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * A test for {@link BuildOptions}. + */ +@RunWith(JUnit4.class) +public class BuildOptionsTest { + private static final ImmutableList<Class<? extends FragmentOptions>> TEST_OPTIONS = + ImmutableList.<Class<? extends FragmentOptions>>of(BuildConfiguration.Options.class); + + @Test + public void testOptionSetCaching() throws Exception { + BuildOptions a = BuildOptions.createDefaults(TEST_OPTIONS); + BuildOptions b = BuildOptions.createDefaults(TEST_OPTIONS); + // The cache keys of the OptionSets must be equal even if these are + // different objects, if they were created with the same options (no options in this case). + assertEquals(a.toString(), b.toString()); + assertEquals(a.computeCacheKey(), b.computeCacheKey()); + } + + @Test + public void testCachingSpecialCases() throws Exception { + // You can add options here to test that their string representations are good. + String[] options = new String[] { "--run_under=//run_under" }; + BuildOptions a = BuildOptions.of(TEST_OPTIONS, options); + BuildOptions b = BuildOptions.of(TEST_OPTIONS, options); + assertEquals(a.toString(), b.toString()); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/ConfigSettingTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/ConfigSettingTest.java new file mode 100644 index 0000000000..e9e89f20b9 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/ConfigSettingTest.java @@ -0,0 +1,183 @@ +// Copyright 2015 Google Inc. 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.analysis.config; + +import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; +import com.google.devtools.build.lib.syntax.Label; + +/** + * Tests for {@link ConfigSetting}. + */ +public class ConfigSettingTest extends BuildViewTestCase { + + private void writeSimpleExample() throws Exception { + scratchFile("pkg/BUILD", + "config_setting(", + " name = 'foo',", + " values = {", + " 'compilation_mode': 'dbg',", + " 'stamp': '1',", + " })"); + } + + private ConfigMatchingProvider getConfigMatchingProvider(String label) throws Exception { + return getConfiguredTarget(label).getProvider(ConfigMatchingProvider.class); + } + + /** + * Tests that a config_setting only matches build configurations where *all* of + * its flag specifications match. + */ + public void testMatchingCriteria() throws Exception { + writeSimpleExample(); + + // First flag mismatches: + useConfiguration("-c", "opt", "--stamp"); + assertFalse(getConfigMatchingProvider("//pkg:foo").matches()); + + // Second flag mismatches: + useConfiguration("-c", "dbg", "--nostamp"); + assertFalse(getConfigMatchingProvider("//pkg:foo").matches()); + + // Both flags mismatch: + useConfiguration("-c", "opt", "--nostamp"); + assertFalse(getConfigMatchingProvider("//pkg:foo").matches()); + + // Both flags match: + useConfiguration("-c", "dbg", "--stamp"); + assertTrue(getConfigMatchingProvider("//pkg:foo").matches()); + } + + /** + * Tests that {@link ConfigMatchingProvider#label} is correct. + */ + public void testLabel() throws Exception { + writeSimpleExample(); + assertEquals( + Label.parseAbsolute("//pkg:foo"), + getConfigMatchingProvider("//pkg:foo").label()); + } + + /** + * Tests that rule analysis fails on unknown options. + */ + public void testUnknownOption() throws Exception { + checkError("foo", "badoption", + "unknown option: 'not_an_option'", + "config_setting(", + " name = 'badoption',", + " values = {'not_an_option': 'bar'})"); + } + + /** + * Tests that rule analysis fails on invalid option values. + */ + public void testInvalidOptionValue() throws Exception { + checkError("foo", "badvalue", + "Not a valid compilation mode: 'baz'", + "config_setting(", + " name = 'badvalue',", + " values = {'compilation_mode': 'baz'})"); + } + + /** + * Tests that when the first option is valid but the config_setting doesn't match, + * remaining options are still validity-checked. + */ + public void testInvalidOptionFartherDown() throws Exception { + checkError("foo", "badoption", + "unknown option: 'not_an_option'", + "config_setting(", + " name = 'badoption',", + " values = {", + " 'compilation_mode': 'opt',", + " 'not_an_option': 'bar',", + " })"); + } + + /** + * Tests that *some* settings must be specified. + */ + public void testEmptySettings() throws Exception { + checkError("foo", "empty", + "//foo:empty: no settings specified", + "config_setting(", + " name = 'empty',", + " values = {})"); + } + + /** + * Tests {@link BuildConfiguration.Fragment#lateBoundOptionDefaults} options (options + * that take alternative defaults from what's specified in {@link + * com.google.devtools.common.options.Option#defaultValue}). + */ + public void testLateBoundOptionDefaults() throws Exception { + scratchFile("test/BUILD", + "config_setting(", + " name = 'match',", + " values = {", + " 'cpu': 'k8',", + " })"); + useConfiguration("--cpu=k8"); + assertTrue(getConfigMatchingProvider("//test:match").matches()); + } + + /** + * Tests matching on multi-value attributes with key=value entries (e.g. --define). + */ + public void testMultiValueDict() throws Exception { + scratchFile("test/BUILD", + "config_setting(", + " name = 'match',", + " values = {", + " 'define': 'foo=bar',", + " })"); + + useConfiguration(""); + assertFalse(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--define", "foo=bar"); + assertTrue(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--define", "foo=baz"); + assertFalse(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--define", "foo=bar", "--define", "bar=baz"); + assertTrue(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--define", "foo=bar", "--define", "bar=baz", "--define", "foo=nope"); + assertFalse(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--define", "foo=nope", "--define", "bar=baz", "--define", "foo=bar"); + assertTrue(getConfigMatchingProvider("//test:match").matches()); + } + + /** + * Tests matching on multi-value attributes with primitive values. + */ + public void testMultiValueList() throws Exception { + scratchFile("test/BUILD", + "config_setting(", + " name = 'match',", + " values = {", + " 'copt': '-Dfoo',", + " })"); + + useConfiguration(""); + assertFalse(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--copt", "-Dfoo"); + assertTrue(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--copt", "-Dbar"); + assertFalse(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--copt", "-Dfoo", "--copt", "-Dbar"); + assertTrue(getConfigMatchingProvider("//test:match").matches()); + useConfiguration("--copt", "-Dbar", "--copt", "-Dfoo"); + assertTrue(getConfigMatchingProvider("//test:match").matches()); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/PerLabelOptionsTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/PerLabelOptionsTest.java new file mode 100644 index 0000000000..aa46f34590 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/PerLabelOptionsTest.java @@ -0,0 +1,84 @@ +// Copyright 2009-2015 Google Inc. 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.analysis.config; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import com.google.common.testing.EqualsTester; +import com.google.devtools.build.lib.util.RegexFilter; +import com.google.devtools.common.options.OptionsParsingException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * A test for {@link PerLabelOptions}. + */ +@RunWith(JUnit4.class) +public class PerLabelOptionsTest { + private PerLabelOptions options = null; + + private PerLabelOptions createOptions(String string) throws OptionsParsingException { + options = new PerLabelOptions.PerLabelOptionsConverter().convert(string); + return options; + } + + private void assertRegexParsing(String filter) throws OptionsParsingException { + RegexFilter regexFilter = new RegexFilter.RegexFilterConverter().convert(filter); + assertEquals(regexFilter.toString(), options.getRegexFilter().toString()); + } + + private void assertOptions(String pattern, String opts, List<String> expectedOptions) + throws OptionsParsingException { + createOptions(pattern + "@" + opts); + assertRegexParsing(pattern); + assertNotNull(options.getOptions()); + assertEquals(expectedOptions, options.getOptions()); + } + + @Test + public void testEmpty() throws Exception { + createOptions(""); + assertRegexParsing(""); + assertThat(options.getOptions()).isEmpty(); + } + + @Test + public void testParsing() throws Exception { + assertOptions("", "", Collections.<String> emptyList()); + assertOptions("", ", ,\t,", Collections.<String> emptyList()); + assertOptions("a/b,+^c,_test$", ", ,\t,", Collections.<String> emptyList()); + assertOptions("a/b,+^c,_test$", "", Collections.<String> emptyList()); + assertOptions("a/b,+^c,_test$", "-g,-O0", Arrays.asList("-g", "-O0")); + assertOptions("a/b,+^c,_test$", "-g@,-O0", Arrays.asList("-g@", "-O0")); + assertOptions("a/b,+^c,_test$", "-g\\,,-O0", Arrays.asList("-g,", "-O0")); + assertOptions("a/b,+^c,_test$", "-g\\,,,,,-O0,,,@,", Arrays.asList("-g,", "-O0", "@")); + } + + @Test + public void testEquals() throws Exception { + new EqualsTester() + .addEqualityGroup(createOptions("a/b,+^c,_test$@-g,-O0"), + createOptions("a/b,+^c,_test$@-g,-O0")) + .addEqualityGroup(createOptions("a/b,+^c,_test$@-O0")) + .testEquals(); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/RunUnderConverterTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/RunUnderConverterTest.java new file mode 100644 index 0000000000..3ba6e57e49 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/RunUnderConverterTest.java @@ -0,0 +1,65 @@ +// Copyright 2007-2015 Google Inc. 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.analysis.config; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.common.options.OptionsParsingException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.List; + +/** + * Tests {@link RunUnderConverter}. + */ +@RunWith(JUnit4.class) +public class RunUnderConverterTest { + + @Test + public void testConverter() throws Exception { + assertEqualsRunUnder("command", null, "command", ImmutableList.<String>of()); + assertEqualsRunUnder("command -c", null, "command", ImmutableList.of("-c")); + assertEqualsRunUnder("command -c --out=all", null, "command", + ImmutableList.of("-c", "--out=all")); + assertEqualsRunUnder("//run:under", "//run:under", null, ImmutableList.<String>of()); + assertEqualsRunUnder("//run:under -c", "//run:under", null, ImmutableList.of("-c")); + assertEqualsRunUnder("//run:under -c --out=all", "//run:under", null, + ImmutableList.of("-c", "--out=all")); + + assertRunUnderFails("", "Empty command"); + } + + private void assertEqualsRunUnder(String input, String label, String command, + List<String> options) throws Exception { + RunUnder runUnder = new RunUnderConverter().convert(input); + assertEquals(label, runUnder.getLabel() == null ? null : runUnder.getLabel().toString()); + assertEquals(command, runUnder.getCommand()); + assertEquals(options, runUnder.getOptions()); + } + + private void assertRunUnderFails(String input, String expectedError) { + try { + new RunUnderConverter().convert(input); + fail(); + } catch (OptionsParsingException e) { + assertThat(e).hasMessage(expectedError); + } + } +} diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/StampTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/StampTest.java new file mode 100644 index 0000000000..8407ec938a --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/StampTest.java @@ -0,0 +1,40 @@ +// Copyright 2010-2015 Google Inc. 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.analysis.config; + +import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; +import com.google.devtools.build.lib.packages.RuleClass; +import com.google.devtools.build.lib.packages.RuleFactory; +import com.google.devtools.build.lib.packages.TargetUtils; +import com.google.devtools.build.lib.packages.TriState; +import com.google.devtools.build.lib.packages.Type; +import com.google.devtools.build.lib.testutil.TestRuleClassProvider; + +/** + * Tests for link stamping. + */ +public class StampTest extends BuildViewTestCase { + /** + * Tests that link stamping is disabled for all tests that support it. + */ + public void testNoStampingForTests() throws Exception { + RuleFactory ruleFactory = new RuleFactory(TestRuleClassProvider.getRuleClassProvider()); + for (String name : ruleFactory.getRuleClassNames()) { + RuleClass ruleClass = ruleFactory.getRuleClass(name); + if (TargetUtils.isTestRuleName(name) && ruleClass.hasAttr("stamp", Type.TRISTATE)) { + assertEquals(TriState.NO, ruleClass.getAttributeByName("stamp").getDefaultValue(null)); + } + } + } +} diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/ConfigurationTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/ConfigurationTestCase.java index c9aec0f6c9..a761b08ff4 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/ConfigurationTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/ConfigurationTestCase.java @@ -113,6 +113,7 @@ public abstract class ConfigurationTestCase extends FoundationTestCase { AnalysisMock analysisMock = getAnalysisMock(); analysisMock.setupMockClient(new MockToolsConfig(rootDirectory)); + analysisMock.setupMockWorkspaceFiles(directories.getEmbeddedBinariesRoot()); configurationFactory = analysisMock.createConfigurationFactory(); buildOptionClasses = analysisMock.getBuildOptions(); } diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java index 66c8a1cf22..2bae9b9335 100644 --- a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java +++ b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java @@ -56,4 +56,6 @@ public class TestConstants { public static final String TEST_RULE_CLASS_PROVIDER = "com.google.devtools.build.lib.bazel.rules.BazelRuleClassProvider"; public static final ImmutableList<String> IGNORED_MESSAGE_PREFIXES = ImmutableList.<String>of(); + + public static final boolean THIS_IS_BAZEL = true; } |