diff --git a/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelper.java b/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelper.java index e5c7d361..4a4db6b9 100644 --- a/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelper.java +++ b/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelper.java @@ -42,7 +42,6 @@ import java.util.Map; import java.util.Scanner; import java.util.Set; -import java.util.TreeSet; import com.salesforce.bazel.sdk.command.BazelWorkspaceCommandRunner; import com.salesforce.bazel.sdk.logging.LogHelper; @@ -132,8 +131,19 @@ private Long generateCacheKey(boolean isSource, String testClassName, BazelProje return key; } + /** + * Convenience bundle of the test param files generated from a set of targets + */ public static class ParamFileResult { - public Set paramFiles = new HashSet<>(); + /** + * The ordered list of param files obtained by querying on the targets + */ + public List paramFiles = new ArrayList<>(); + + /** + * Labels that did not resolve to a param file. Usually means the test class is not referenced by + * a java_test target, but is a different kind of test that we don't know how to run. + */ public Set unrunnableLabels = new HashSet<>(); } @@ -282,11 +292,22 @@ public Set findParamsFileForTestClassnameAndTarget(BazelWorkspace bazelWor * Given the set of param files in the passed testParamFilesResult, parse each param file and extract a list * of jar files from the sources and output sections of each file. Then assemble a de-duplicated list of these * jar files. The path for each jar file comes from the param file and is known to be relative to the Bazel - * exec root of the workspace. + * exec root of the workspace. + *

+ * @param testParamFiles the ordered list of discovered param files for the set of targets + * @param includeDeployJars deploy jars contain the Bazel test runner and the full classpath of classes to run + * the test. For some environments, this isn't necessary because the environment externally specifies + * the classpath at launch, and provides the test runner (e.g. Eclipse RemoteTestRunner) + * @return a List of paths to jar files; the list is ordered the same as the param files */ - public Set aggregateJarFilesFromParamFiles(BazelJvmTestClasspathHelper.ParamFileResult testParamFilesResult) { - Set allPaths = new TreeSet<>(); - for (File paramsFile : testParamFilesResult.paramFiles) { + public List aggregateJarFilesFromParamFiles(List testParamFiles, + boolean includeDeployJars) { + + // Bazel is deterministic in the ordering of classpath elements, so use a list here not a Set + // to allow us to better model the classpath order of Bazel + List allPaths = new ArrayList<>(); + + for (File paramsFile : testParamFiles) { List jarPaths = null; try { jarPaths = getClasspathJarsFromParamsFile(paramsFile); @@ -299,6 +320,15 @@ public Set aggregateJarFilesFromParamFiles(BazelJvmTestClasspathHelper.P } for (String jarPath : jarPaths) { + if (!includeDeployJars && jarPath.endsWith("_deploy.jar")) { + // deploy jars are bloated and redundant for some callers, exclude them if asked to + continue; + } + if (allPaths.contains(jarPath)) { + // we don't want dupes + continue; + } + // it is important to use a Set for allPaths, as the jarPaths will contain many dupes // across ParamFiles and we only want each one listed once allPaths.add(jarPath); diff --git a/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/logging/BasicLoggerFacade.java b/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/logging/BasicLoggerFacade.java index af09b262..ffda4852 100644 --- a/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/logging/BasicLoggerFacade.java +++ b/bundles/com.salesforce.bazel-java-sdk/src/main/java/com/salesforce/bazel/sdk/logging/BasicLoggerFacade.java @@ -48,6 +48,13 @@ public class BasicLoggerFacade extends LoggerFacade { @Override protected void error(Class from, String message, Object... args) { // LoggerFactory.getLogger(from).error(message, args); + if (args != null && args.length > 0) { + Object firstArg = args[0]; + if (firstArg instanceof Throwable) { + Throwable anyE = (Throwable)firstArg; + anyE.printStackTrace(); + } + } System.err.println("ERROR " + formatMsg(from, message, args)); } diff --git a/bundles/com.salesforce.bazel.eclipse.common/src/main/java/com/salesforce/bazel/eclipse/classpath/BazelClasspathContainerInitializer.java b/bundles/com.salesforce.bazel.eclipse.common/src/main/java/com/salesforce/bazel/eclipse/classpath/BazelClasspathContainerInitializer.java index 49551a0d..52966a97 100644 --- a/bundles/com.salesforce.bazel.eclipse.common/src/main/java/com/salesforce/bazel/eclipse/classpath/BazelClasspathContainerInitializer.java +++ b/bundles/com.salesforce.bazel.eclipse.common/src/main/java/com/salesforce/bazel/eclipse/classpath/BazelClasspathContainerInitializer.java @@ -72,6 +72,7 @@ public class BazelClasspathContainerInitializer extends ClasspathContainerInitia @Override public void initialize(IPath eclipseProjectPath, IJavaProject eclipseJavaProject) throws CoreException { IProject eclipseProject = eclipseJavaProject.getProject(); + String eclipseProjectName = eclipseProject.getName(); try { //remove projects added to the workspace after a corrupted package in identified if (isCorrupt.get()) { @@ -81,7 +82,7 @@ public void initialize(IPath eclipseProjectPath, IJavaProject eclipseJavaProject // create the BazelProject if necessary BazelProjectManager bazelProjectManager = ComponentContext.getInstance().getProjectManager(); - BazelProject bazelProject = bazelProjectManager.getProject(eclipseProject.getName()); + BazelProject bazelProject = bazelProjectManager.getProject(eclipseProjectName); if (bazelProject == null) { bazelProject = new BazelProject(eclipseProject.getName(), eclipseProject); bazelProjectManager.addProject(bazelProject); @@ -95,10 +96,10 @@ public void initialize(IPath eclipseProjectPath, IJavaProject eclipseJavaProject } else { setClasspathContainerForProject(eclipseProjectPath, eclipseJavaProject, container); } - } catch (IOException | InterruptedException | BackingStoreException e) { - LOG.error("Error while creating Bazel classpath container.", e); } catch (BazelCommandLineToolConfigurationException e) { LOG.error("Bazel not found: " + e.getMessage()); + } catch (Exception anyE) { + LOG.error("Error while initializing Bazel classpath container for project {}", anyE, eclipseProjectName); } } diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/main/java/com/salesforce/bazel/eclipse/launch/BazelTestClasspathProvider.java b/bundles/com.salesforce.bazel.eclipse.core/src/main/java/com/salesforce/bazel/eclipse/launch/BazelTestClasspathProvider.java index 4f5c08f6..a783b092 100644 --- a/bundles/com.salesforce.bazel.eclipse.core/src/main/java/com/salesforce/bazel/eclipse/launch/BazelTestClasspathProvider.java +++ b/bundles/com.salesforce.bazel.eclipse.core/src/main/java/com/salesforce/bazel/eclipse/launch/BazelTestClasspathProvider.java @@ -177,9 +177,12 @@ IRuntimeClasspathEntry[] computeUnresolvedClasspathFromParamFiles(File execRootD BazelJvmTestClasspathHelper.ParamFileResult testParamFilesResult) throws CoreException { List result = new ArrayList<>(); - // assemble the de-duplicated list of jar files that are used across all the test targets - // these paths are listed in the param files, and are relative to the Bazel workspace exec root - Set jarPaths = bazelJvmTestClasspathHelper.aggregateJarFilesFromParamFiles(testParamFilesResult); + // Assemble the de-duplicated list of jar files that are used across all the test targets + // these paths are listed in the param files, and are relative to the Bazel workspace exec root. + // We don't want deploy jars, because those are bloated and kill performance. Eclipse passes the project classpath + // to the RemoteTestRunner JVM so we don't need the self-contained deploy jars. + boolean includeDeployJars = false; + List jarPaths = bazelJvmTestClasspathHelper.aggregateJarFilesFromParamFiles(testParamFilesResult.paramFiles, includeDeployJars); for (String rawPath : jarPaths) { String canonicalPath = FSPathHelper.getCanonicalPathStringSafely(new File(execRootDir, rawPath)); IPath eachPath = new Path(canonicalPath); diff --git a/tests/com.salesforce.bazel-java-sdk.tests/src/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelperTest.java b/tests/com.salesforce.bazel-java-sdk.tests/src/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelperTest.java index 52f99ef7..fddd52d1 100644 --- a/tests/com.salesforce.bazel-java-sdk.tests/src/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelperTest.java +++ b/tests/com.salesforce.bazel-java-sdk.tests/src/com/salesforce/bazel/sdk/lang/jvm/BazelJvmTestClasspathHelperTest.java @@ -28,16 +28,15 @@ import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; +import java.util.ArrayList; import java.util.List; import java.util.Scanner; -import java.util.Set; import java.util.TreeSet; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import com.salesforce.bazel.sdk.lang.jvm.BazelJvmTestClasspathHelper; import com.salesforce.bazel.sdk.path.FSPathHelper; public class BazelJvmTestClasspathHelperTest { @@ -82,7 +81,7 @@ public void getParamsJarSuffix() { @Test public void testClasspathAggregation() throws Exception { BazelJvmTestClasspathHelper.ParamFileResult result = new BazelJvmTestClasspathHelper.ParamFileResult(); - result.paramFiles = new TreeSet<>(); + result.paramFiles = new ArrayList<>(); result.unrunnableLabels = new TreeSet<>(); File tdir = tmpDir.newFolder("paramFiles"); File pdir = new File(tdir, "paramFiles"); @@ -95,9 +94,14 @@ public void testClasspathAggregation() throws Exception { result.paramFiles.add(createParamFile(pdir, i)); } - Set jarPaths = bazelJvmTestClasspathHelper.aggregateJarFilesFromParamFiles(result); - + boolean includeDeployJars = true; + List jarPaths = + bazelJvmTestClasspathHelper.aggregateJarFilesFromParamFiles(result.paramFiles, includeDeployJars); assertEquals(7, jarPaths.size()); + + includeDeployJars = false; + jarPaths = bazelJvmTestClasspathHelper.aggregateJarFilesFromParamFiles(result.paramFiles, includeDeployJars); + assertEquals(5, jarPaths.size()); } private static File createParamFile(File dir, int index) {