Search in sources :

Example 1 with LinkageProblem

use of com.google.cloud.tools.opensource.classpath.LinkageProblem in project cloud-opensource-java by GoogleCloudPlatform.

the class LinkageMonitor method messageForFixedErrors.

/**
 * Returns a message on {@code fixedProblems}.
 */
@VisibleForTesting
static String messageForFixedErrors(Set<LinkageProblem> fixedProblems) {
    int problemSize = fixedProblems.size();
    StringBuilder message = new StringBuilder("The following problem" + (problemSize > 1 ? "s" : "") + " in the baseline no longer appear in the snapshot:\n");
    for (LinkageProblem problem : fixedProblems) {
        message.append("  " + problem.formatSymbolProblem() + "\n");
    }
    return message.toString();
}
Also used : LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 2 with LinkageProblem

use of com.google.cloud.tools.opensource.classpath.LinkageProblem in project cloud-opensource-java by GoogleCloudPlatform.

the class LinkageMonitor method main.

public static void main(String[] arguments) throws RepositoryException, IOException, MavenRepositoryException, ModelBuildingException {
    CommandLine commandLine = parseCommandLine(arguments);
    String bomCoordinates = commandLine.getArgList().get(0);
    List<String> coordinatesElements = Splitter.on(':').splitToList(bomCoordinates);
    if (coordinatesElements.size() != 2) {
        logger.severe("Please specify BOM coordinates without version. Example:" + " com.google.cloud:libraries-bom");
        System.exit(1);
    }
    Set<LinkageProblem> newLinkageProblems = new LinkageMonitor().run(coordinatesElements.get(0), coordinatesElements.get(1));
    int errorSize = newLinkageProblems.size();
    if (errorSize > 0) {
        logger.severe(String.format("Found %d new linkage error%s", errorSize, errorSize > 1 ? "s" : ""));
        logger.info("For the details of the linkage errors, see " + "https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-Messages");
        // notify CI tools of the failure
        System.exit(1);
    } else {
        logger.info("No new problem found");
    }
}
Also used : CommandLine(org.apache.commons.cli.CommandLine) LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem)

Example 3 with LinkageProblem

use of com.google.cloud.tools.opensource.classpath.LinkageProblem in project cloud-opensource-java by GoogleCloudPlatform.

the class LinkageMonitor method messageForNewErrors.

/**
 * Returns a message on {@code snapshotProblems} that do not exist in {@code baselineProblems}.
 */
@VisibleForTesting
static String messageForNewErrors(Set<LinkageProblem> snapshotProblems, Set<LinkageProblem> baselineProblems, ClassPathResult classPathResult) {
    Set<LinkageProblem> newProblems = Sets.difference(snapshotProblems, baselineProblems);
    Builder<ClassPathEntry> problematicJars = ImmutableSet.builder();
    ImmutableListMultimap<String, LinkageProblem> groupedBySymbolProblem = Multimaps.index(newProblems, problem -> problem.formatSymbolProblem());
    StringBuilder message = new StringBuilder("Newly introduced problem" + (groupedBySymbolProblem.keySet().size() > 1 ? "s" : "") + ":\n");
    for (String problem : groupedBySymbolProblem.keySet()) {
        message.append(problem + "\n");
        for (LinkageProblem linkageProblem : groupedBySymbolProblem.get(problem)) {
            // This is null for ClassNotFound error.
            if (linkageProblem.getTargetClass() != null) {
                problematicJars.add(linkageProblem.getTargetClass().getClassPathEntry());
            }
            ClassFile sourceClass = linkageProblem.getSourceClass();
            message.append(String.format("  referenced from %s (%s)\n", sourceClass.getBinaryName(), sourceClass.getClassPathEntry()));
            problematicJars.add(sourceClass.getClassPathEntry());
        }
    }
    message.append("\n");
    message.append(classPathResult.formatDependencyPaths(problematicJars.build()));
    return message.toString();
}
Also used : LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) ClassFile(com.google.cloud.tools.opensource.classpath.ClassFile) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 4 with LinkageProblem

use of com.google.cloud.tools.opensource.classpath.LinkageProblem in project cloud-opensource-java by GoogleCloudPlatform.

the class MaximumLinkageErrorsTest method testForNewLinkageErrors.

@Test
public void testForNewLinkageErrors() throws IOException, MavenRepositoryException, RepositoryException {
    // Not using RepositoryUtility.findLatestCoordinates, which may return a snapshot version
    String version = findLatestNonSnapshotVersion();
    String baselineCoordinates = "com.google.cloud:libraries-bom:" + version;
    Bom baseline = Bom.readBom(baselineCoordinates);
    Path bomFile = Paths.get("../cloud-oss-bom/pom.xml");
    Bom bom = Bom.readBom(bomFile);
    ImmutableSet<LinkageProblem> oldProblems = LinkageChecker.create(baseline).findLinkageProblems();
    LinkageChecker checker = LinkageChecker.create(bom);
    ImmutableSet<LinkageProblem> currentProblems = checker.findLinkageProblems();
    // This only tests for newly missing methods, not new invocations of
    // previously missing methods.
    Set<LinkageProblem> newProblems = Sets.difference(currentProblems, oldProblems);
    // Appengine-api-1.0-sdk is known to contain linkage errors because it shades dependencies
    // https://github.com/GoogleCloudPlatform/cloud-opensource-java/issues/441
    newProblems = newProblems.stream().filter(problem -> !hasLinkageProblemFromArtifactId(problem, "appengine-api-1.0-sdk")).collect(Collectors.toSet());
    // Check that no new linkage errors have been introduced since the baseline
    StringBuilder message = new StringBuilder("Baseline BOM: " + baselineCoordinates + "\n");
    if (!newProblems.isEmpty()) {
        message.append("Newly introduced problems:\n");
        message.append(LinkageProblem.formatLinkageProblems(newProblems, null));
        Assert.fail(message.toString());
    }
}
Also used : Path(java.nio.file.Path) Bom(com.google.cloud.tools.opensource.dependencies.Bom) LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) LinkageChecker(com.google.cloud.tools.opensource.classpath.LinkageChecker) Test(org.junit.Test)

Example 5 with LinkageProblem

use of com.google.cloud.tools.opensource.classpath.LinkageProblem in project cloud-opensource-java by GoogleCloudPlatform.

the class LinkageCheckTask method findLinkageErrors.

/**
 * Returns true iff {@code configuration}'s artifacts contain linkage errors.
 */
private boolean findLinkageErrors(Configuration configuration) throws IOException {
    ClassPathResult classPathResult = createClassPathResult(configuration.getResolvedConfiguration());
    ImmutableList.Builder<ClassPathEntry> classPathEntriesBuilder = ImmutableList.builder();
    for (ResolvedArtifact resolvedArtifact : configuration.getResolvedConfiguration().getResolvedArtifacts()) {
        ModuleVersionIdentifier moduleVersionId = resolvedArtifact.getModuleVersion().getId();
        DefaultArtifact artifact = new DefaultArtifact(moduleVersionId.getGroup(), moduleVersionId.getName(), resolvedArtifact.getClassifier(), resolvedArtifact.getExtension(), moduleVersionId.getVersion(), null, resolvedArtifact.getFile());
        classPathEntriesBuilder.add(new ClassPathEntry(artifact));
    }
    ImmutableList<ClassPathEntry> classPath = classPathEntriesBuilder.build();
    if (!classPath.isEmpty()) {
        String exclusionFileName = extension.getExclusionFile();
        Path exclusionFile = exclusionFileName == null ? null : Paths.get(exclusionFileName);
        if (exclusionFile != null && !exclusionFile.isAbsolute()) {
            // Relative path from the project root
            Path projectRoot = getProject().getRootDir().toPath();
            exclusionFile = projectRoot.resolve(exclusionFile).toAbsolutePath();
        }
        // TODO(suztomo): Specify correct entry points if reportOnlyReachable is true.
        LinkageChecker linkageChecker = LinkageChecker.create(classPath, classPath, exclusionFile);
        ImmutableSet<LinkageProblem> linkageProblems = linkageChecker.findLinkageProblems();
        ClassPathBuilder classPathBuilder = new ClassPathBuilder();
        LinkageProblemCauseAnnotator.annotate(classPathBuilder, classPathResult, linkageProblems);
        int errorCount = linkageProblems.size();
        // TODO(suztomo): Show the dependency paths to the problematic artifacts.
        if (errorCount > 0) {
            getLogger().error("Linkage Checker rule found {} error{}:\n{}", errorCount, errorCount > 1 ? "s" : "", LinkageProblem.formatLinkageProblems(linkageProblems, classPathResult));
            ResolutionResult result = configuration.getIncoming().getResolutionResult();
            ResolvedComponentResult root = result.getRoot();
            String dependencyPaths = dependencyPathsOfProblematicJars(root, linkageProblems);
            getLogger().error(dependencyPaths);
            getLogger().info("For the details of the linkage errors, see " + "https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-Messages");
        }
        return errorCount > 0;
    }
    // When the configuration does not have any artifacts, there's no linkage error.
    return false;
}
Also used : AnnotatedClassPath(com.google.cloud.tools.opensource.classpath.AnnotatedClassPath) Path(java.nio.file.Path) DependencyPath(com.google.cloud.tools.opensource.dependencies.DependencyPath) ResolvedArtifact(org.gradle.api.artifacts.ResolvedArtifact) LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) ImmutableList(com.google.common.collect.ImmutableList) ResolutionResult(org.gradle.api.artifacts.result.ResolutionResult) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) ClassPathBuilder(com.google.cloud.tools.opensource.classpath.ClassPathBuilder) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry) ModuleVersionIdentifier(org.gradle.api.artifacts.ModuleVersionIdentifier) LinkageChecker(com.google.cloud.tools.opensource.classpath.LinkageChecker) ResolvedComponentResult(org.gradle.api.artifacts.result.ResolvedComponentResult) DefaultArtifact(org.eclipse.aether.artifact.DefaultArtifact)

Aggregations

LinkageProblem (com.google.cloud.tools.opensource.classpath.LinkageProblem)11 ClassPathEntry (com.google.cloud.tools.opensource.classpath.ClassPathEntry)7 ClassPathResult (com.google.cloud.tools.opensource.classpath.ClassPathResult)5 DefaultArtifact (org.eclipse.aether.artifact.DefaultArtifact)5 LinkageChecker (com.google.cloud.tools.opensource.classpath.LinkageChecker)4 DependencyPath (com.google.cloud.tools.opensource.dependencies.DependencyPath)4 Path (java.nio.file.Path)4 ClassFile (com.google.cloud.tools.opensource.classpath.ClassFile)3 ClassPathBuilder (com.google.cloud.tools.opensource.classpath.ClassPathBuilder)3 Artifact (org.eclipse.aether.artifact.Artifact)3 AnnotatedClassPath (com.google.cloud.tools.opensource.classpath.AnnotatedClassPath)2 Bom (com.google.cloud.tools.opensource.dependencies.Bom)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 Test (org.junit.Test)2 ClassNotFoundProblem (com.google.cloud.tools.opensource.classpath.ClassNotFoundProblem)1 ClassReferenceGraph (com.google.cloud.tools.opensource.classpath.ClassReferenceGraph)1 ClassSymbol (com.google.cloud.tools.opensource.classpath.ClassSymbol)1 DependencyMediation (com.google.cloud.tools.opensource.classpath.DependencyMediation)1 GradleDependencyMediation (com.google.cloud.tools.opensource.classpath.GradleDependencyMediation)1 DependencyGraphBuilder (com.google.cloud.tools.opensource.dependencies.DependencyGraphBuilder)1