Add an AnalysisMock for Bazel; all the analysis action tests pass.

Change-Id: I83a280d53272972bace811b1493825b5dc48a4d2

--
MOS_MIGRATED_REVID=87608375
diff --git a/src/test/java/BUILD b/src/test/java/BUILD
index 7fde4f2..c62c788 100644
--- a/src/test/java/BUILD
+++ b/src/test/java/BUILD
@@ -144,16 +144,11 @@
     ],
 )
 
-java_test(
-    name = "actions_test",
+java_library(
+    name = "actions_testutil",
     srcs = glob([
-        "com/google/devtools/build/lib/actions/**/*.java",
+        "com/google/devtools/build/lib/actions/util/*.java",
     ]),
-    args = ["com.google.devtools.build.lib.AllTests"],
-    data = [
-        "//src/main/native:libunix.dylib",
-        "//src/main/native:libunix.so",
-    ],
     deps = [
         ":foundations_testutil",
         ":test_runner",
@@ -168,21 +163,48 @@
     ],
 )
 
-# TODO(bazel-team): Make these tests actually run. Also fix the duplicate compilation of
-# actions/util.
-java_library(
-    name = "analysis_actions_test",
+java_test(
+    name = "actions_test",
     srcs = glob([
-        "com/google/devtools/build/lib/actions/util/*.java",
-        "com/google/devtools/build/lib/analysis/**/*.java",
-        "com/google/devtools/build/lib/exec/util/*.java",
-        "com/google/devtools/build/lib/packages/util/*.java",
+        "com/google/devtools/build/lib/actions/*.java",
     ]),
+    args = ["com.google.devtools.build.lib.AllTests"],
     data = [
         "//src/main/native:libunix.dylib",
         "//src/main/native:libunix.so",
     ],
     deps = [
+        ":actions_testutil",
+        ":foundations_testutil",
+        ":test_runner",
+        ":testutil",
+        "//src/main/java:bazel-core",
+        "//third_party:guava",
+        "//third_party:guava-testlib",
+        "//third_party:jsr305",
+        "//third_party:junit4",
+        "//third_party:mockito",
+        "//third_party:truth",
+    ],
+)
+
+java_library(
+    name = "analysis_actions_test",
+    srcs = glob([
+        "com/google/devtools/build/lib/analysis/**/*.java",
+        "com/google/devtools/build/lib/exec/util/*.java",
+        "com/google/devtools/build/lib/packages/util/*.java",
+    ]),
+    #     args = ["com.google.devtools.build.lib.AllTests"],
+    data = [
+        "//src/main/native:libunix.dylib",
+        "//src/main/native:libunix.so",
+    ],
+    resources = [
+        "MOCK_CROSSTOOL",
+    ],
+    deps = [
+        ":actions_testutil",
         ":foundations_testutil",
         ":test_runner",
         ":testutil",
diff --git a/src/test/java/MOCK_CROSSTOOL b/src/test/java/MOCK_CROSSTOOL
new file mode 100644
index 0000000..c57df53
--- /dev/null
+++ b/src/test/java/MOCK_CROSSTOOL
@@ -0,0 +1,197 @@
+# 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.
+
+major_version: "local"
+minor_version: ""
+default_target_cpu: "k8"
+default_toolchain {
+  cpu: "k8"
+  toolchain_identifier: "local_linux"
+}
+default_toolchain {
+  cpu: "darwin"
+  toolchain_identifier: "local_darwin"
+}
+
+toolchain {
+  abi_version: "local"
+  abi_libc_version: "local"
+  builtin_sysroot: ""
+  compiler: "compiler"
+  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"
+
+  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" }
+  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"
+  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: "compiler"
+  host_system_name: "local"
+  needsPic: true
+  target_libc: "macosx"
+  target_cpu: "darwin"
+  target_system_name: "local"
+  toolchain_identifier: "local_darwin"
+
+  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" }
+  cxx_flag: "-std=c++0x"
+  ar_flag: "-static"
+  ar_flag: "-s"
+  ar_flag: "-o"
+  linker_flag: "-lstdc++"
+  cxx_builtin_include_directory: "/usr/include"
+  cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain"
+  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"
+  host_system_name: "local"
+  needsPic: false
+  target_libc: "local"
+  target_cpu: "k8"
+  target_system_name: "local"
+  toolchain_identifier: "local_windows_mingw"
+
+  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" }
+}
+
+toolchain {
+  abi_version: "local"
+  abi_libc_version: "local"
+  builtin_sysroot: ""
+  compiler: "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"
+
+  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" }
+}
+
+toolchain {
+  abi_version: "local"
+  abi_libc_version: "local"
+  builtin_sysroot: ""
+  compiler: "windows_clang"
+  host_system_name: "local"
+  needsPic: false
+  target_libc: "local"
+  target_cpu: "k8"
+  target_system_name: "local"
+  toolchain_identifier: "local_windows_clang"
+
+  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" }
+}
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
new file mode 100644
index 0000000..be20313
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/BazelAnalysisMock.java
@@ -0,0 +1,89 @@
+// 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;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.lib.analysis.config.ConfigurationFactory;
+import com.google.devtools.build.lib.analysis.util.AnalysisMock;
+import com.google.devtools.build.lib.bazel.rules.BazelConfiguration;
+import com.google.devtools.build.lib.bazel.rules.BazelConfigurationCollection;
+import com.google.devtools.build.lib.bazel.rules.BazelRuleClassProvider;
+import com.google.devtools.build.lib.packages.util.MockToolsConfig;
+import com.google.devtools.build.lib.rules.cpp.CppConfigurationLoader;
+import com.google.devtools.build.lib.rules.java.JavaConfigurationLoader;
+import com.google.devtools.build.lib.rules.java.JvmConfigurationLoader;
+import com.google.devtools.build.lib.rules.objc.ObjcConfigurationLoader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+
+public class BazelAnalysisMock extends AnalysisMock {
+  public static final AnalysisMock INSTANCE = new BazelAnalysisMock();
+
+  @Override
+  public void setupMockClient(MockToolsConfig config) throws IOException {
+    config.create("tools/jdk/BUILD",
+        "package(default_visibility=['//visibility:public'])",
+        "java_toolchain(name = 'toolchain', encoding = 'UTF-8', source_version = '8', ",
+        "  target_version = '8')",
+        "filegroup(name = 'jdk-null')",
+        "filegroup(name = 'jdk-default', srcs = [':java'], path = 'jdk/jre')",
+        "filegroup(name = 'jdk', srcs = [':jdk-default', ':jdk-null'])",
+        "filegroup(name='langtools', srcs=['jdk/lib/tools.jar'])",
+        "filegroup(name='bootclasspath', srcs=['jdk/jre/lib/rt.jar'])",
+        "filegroup(name='java', srcs = ['jdk/jre/bin/java'])",
+        "exports_files(['JavaBuilder_deploy.jar','SingleJar_deploy.jar',",
+        "               '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-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',)");
+    config.create("tools/cpp/CROSSTOOL", readFromResources("MOCK_CROSSTOOL"));
+  }
+
+  public static String readFromResources(String filename) {
+    try (InputStream in = BazelAnalysisMock.class.getClassLoader().getResourceAsStream(filename)) {
+      return new String(ByteStreams.toByteArray(in), StandardCharsets.UTF_8);
+    } catch (IOException e) {
+      // This should never happen.
+      throw new AssertionError(e);
+    }
+  }
+
+  @Override
+  public ConfigurationFactory createConfigurationFactory() {
+    return new ConfigurationFactory(new BazelConfigurationCollection(),
+        new BazelConfiguration.Loader(),
+        new CppConfigurationLoader(Functions.<String>identity()),
+        new JvmConfigurationLoader(BazelRuleClassProvider.JAVA_CPU_SUPPLIER),
+        new JavaConfigurationLoader(BazelRuleClassProvider.JAVA_CPU_SUPPLIER),
+        new ObjcConfigurationLoader());
+  }
+
+  @Override
+  public Collection<String> getOptionOverrides() {
+    return ImmutableList.of();
+  }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java
index fcf9b6f..0ea49bf 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java
@@ -48,7 +48,9 @@
       @Nullable Path runfilesDirectoryOpt) {
     this.rootDirectory = rootDirectory;
     this.realFileSystem = realFileSystem;
-    if (runfilesDirectoryOpt == null) {
+    if (!realFileSystem) {
+      this.runfilesDirectory = null;
+    } else if (runfilesDirectoryOpt == null) {
       this.runfilesDirectory = rootDirectory.getRelative(BlazeTestUtils.runfilesDir());
     } else {
       this.runfilesDirectory = runfilesDirectoryOpt;
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 28ca6bf..85205a6 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
@@ -44,7 +44,8 @@
   /**
    * Name of a class with an INSTANCE field of type AnalysisMock to be used for analysis tests.
    */
-  public static final String TEST_ANALYSIS_MOCK = "DOES-NOT-WORK-YET";
+  public static final String TEST_ANALYSIS_MOCK =
+      "com.google.devtools.build.lib.analysis.BazelAnalysisMock";
 
   /**
    * Directory where we can find bazel's Java tests, relative to a test's runfiles directory.