This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 0231dba4c3d CAMEL-21250: camel-report-maven-plugin - Can we cover anonymous routes if loaded from xml files (#16687) 0231dba4c3d is described below commit 0231dba4c3d238191f1614289617f86b25cadca6 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Jan 2 14:26:41 2025 +0100 CAMEL-21250: camel-report-maven-plugin - Can we cover anonymous routes if loaded from xml files (#16687) --- .../org/apache/camel/maven/RouteCoverageMojo.java | 80 ++++++++++++++++++---- .../camel/parser/helper/RouteCoverageHelper.java | 49 +++++++++++++ .../apache/camel/parser/model/CoverageData.java | 11 ++- .../management/mbean/RouteCoverageXmlParser.java | 4 ++ 4 files changed, 129 insertions(+), 15 deletions(-) diff --git a/catalog/camel-report-maven-plugin/src/main/java/org/apache/camel/maven/RouteCoverageMojo.java b/catalog/camel-report-maven-plugin/src/main/java/org/apache/camel/maven/RouteCoverageMojo.java index c0681586dd3..c803450584c 100644 --- a/catalog/camel-report-maven-plugin/src/main/java/org/apache/camel/maven/RouteCoverageMojo.java +++ b/catalog/camel-report-maven-plugin/src/main/java/org/apache/camel/maven/RouteCoverageMojo.java @@ -182,7 +182,8 @@ public class RouteCoverageMojo extends AbstractMojo { int totalNumberOfNodes = 0; List<CamelNodeDetails> routeIdTrees = routeTrees.stream().filter(t -> t.getRouteId() != null).toList(); - List<CamelNodeDetails> anonymousRouteTrees = routeTrees.stream().filter(t -> t.getRouteId() == null).toList(); + List<CamelNodeDetails> anonymousRouteTrees + = new ArrayList<>(routeTrees.stream().filter(t -> t.getRouteId() == null).toList()); Document document = null; File file = null; Element report = null; @@ -220,18 +221,48 @@ public class RouteCoverageMojo extends AbstractMojo { // grab dump data for the route totalNumberOfNodes - = grabDumpData(t, routeId, totalNumberOfNodes, fileName, notCovered, coveredNodes, report, document, + += grabDumpData(t, routeId, totalNumberOfNodes, fileName, notCovered, coveredNodes, report, document, sourceFileName, pack); } + List<CamelNodeDetails> anonymousHandled = new ArrayList<>(); + for (CamelNodeDetails t : anonymousRouteTrees) { + String fileName = stripRootPath(asRelativeFile(t.getFileName(), project), project); + String sourceFileName = new File(fileName).getName(); + String packageName = new File(fileName).getParent(); + String loc = sourceFileName + ":" + t.getLineNumber(); + Element pack = null; - if (report != null) { - doGenerateJacocoReport(file, document); + if (report != null) { + // package tag + pack = document.createElement("package"); + createAttrString(document, pack, "name", packageName); + report.appendChild(pack); + } + + // grab dump data for the route + int extra = grabDumpDataBySourceLocation(t, loc, totalNumberOfNodes, fileName, notCovered, coveredNodes, report, + document, + sourceFileName, pack); + if (extra > 0) { + anonymousHandled.add(t); + } + totalNumberOfNodes += extra; } + anonymousRouteTrees.removeAll(anonymousHandled); - if (anonymousRoutes && !anonymousRouteTrees.isEmpty()) { - totalNumberOfNodes = handleAnonymousRoutes(anonymousRouteTrees, totalNumberOfNodes, notCovered, coveredNodes); + if (!anonymousRouteTrees.isEmpty()) { + if (anonymousRoutes) { + totalNumberOfNodes = handleAnonymousRoutes(anonymousRouteTrees, totalNumberOfNodes, notCovered, coveredNodes); + } else { + getLog().warn( + "Discovered " + anonymousRouteTrees.size() + + " anonymous routes. Add route ids to these routes for route coverage support."); + } } + if (report != null) { + doGenerateJacocoReport(file, document); + } if (generateHtmlReport) { doGenerateHtmlReport(); } @@ -279,14 +310,6 @@ public class RouteCoverageMojo extends AbstractMojo { getLog().info("Discovered " + routeTrees.size() + " routes"); - // skip any routes which has no route id assigned - - long anonymous = routeTrees.stream().filter(t -> t.getRouteId() == null).count(); - if (!anonymousRoutes && anonymous > 0) { - getLog().warn( - "Discovered " + anonymous + " anonymous routes. Add route ids to these routes for route coverage support."); - } - return routeTrees; } @@ -318,6 +341,35 @@ public class RouteCoverageMojo extends AbstractMojo { return totalNumberOfNodes; } + private int grabDumpDataBySourceLocation( + CamelNodeDetails t, String sourceLocation, int totalNumberOfNodes, String fileName, AtomicInteger notCovered, + AtomicInteger coveredNodes, Element report, Document document, String sourceFileName, Element pack) + throws MojoExecutionException { + try { + List<CoverageData> coverageData = RouteCoverageHelper + .parseDumpRouteCoverageByLineNumber(project.getBasedir() + DESTINATION_DIR, sourceLocation); + if (coverageData.isEmpty()) { + getLog().warn("No route coverage data found for route: " + sourceLocation + + ". Make sure to enable route coverage in your unit tests and assign unique route ids to your routes. Also remember to run unit tests first."); + } else { + List<RouteCoverageNode> coverage = gatherRouteCoverageSummary(List.of(t), coverageData); + totalNumberOfNodes += coverage.size(); + String routeId = coverageData.get(0).getRouteId(); + String out = templateCoverageData(fileName, routeId, coverage, notCovered, coveredNodes); + getLog().info("Route coverage summary:\n\n" + out); + getLog().info(""); + + if (report != null) { + appendSourcefileNode(document, sourceFileName, pack, coverage); + } + } + + } catch (Exception e) { + throw new MojoExecutionException("Error during gathering route coverage data for route: " + sourceFileName, e); + } + return totalNumberOfNodes; + } + private void doGenerateJacocoReport(File file, Document document) { try { getLog().info("Generating Jacoco XML report: " + file + "\n\n"); diff --git a/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/helper/RouteCoverageHelper.java b/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/helper/RouteCoverageHelper.java index ceb3d5bc265..1a696231414 100644 --- a/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/helper/RouteCoverageHelper.java +++ b/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/helper/RouteCoverageHelper.java @@ -81,6 +81,55 @@ public final class RouteCoverageHelper { return answer; } + /** + * Parses the dumped route coverage data and creates a line by line coverage data + * + * @param directory the directory with the dumped route coverage data + * @param sourceLocation the location of the route (filename:line) + * @return line by line coverage data + */ + public static List<CoverageData> parseDumpRouteCoverageByLineNumber(String directory, String sourceLocation) + throws Exception { + List<CoverageData> answer = new ArrayList<>(); + + if (sourceLocation == null) { + return answer; + } + + File[] files = new File(directory).listFiles(f -> f.getName().endsWith(".xml")); + if (files == null) { + return answer; + } + + CamelCatalog catalog = new DefaultCamelCatalog(true); + + for (File file : files) { + try (FileInputStream fis = new FileInputStream(file)) { + Document dom = XmlLineNumberParser.parseXml(fis); + NodeList routes = dom.getElementsByTagName("route"); + for (int i = 0; i < routes.getLength(); i++) { + Node route = routes.item(i); + Node n = route.getAttributes().getNamedItem("id"); + String id = n != null ? n.getNodeValue() : null; + n = route.getAttributes().getNamedItem("sourceLocation"); + String loc = n != null ? n.getNodeValue() : null; + if (sourceLocation.equals(loc)) { + // parse each route and build a List<CoverageData> for line by line coverage data + AtomicInteger counter = new AtomicInteger(); + List<CoverageData> list = new ArrayList<>(); + parseRouteData(catalog, route, list, counter); + if (id != null && !list.isEmpty()) { + list.get(0).setRouteId(id); + } + answer.addAll(list); + } + } + } + } + + return answer; + } + public static Map<String, List<CoverageData>> parseDumpRouteCoverageByClassAndTestMethod(String directory) throws Exception { Map<String, List<CoverageData>> answer = new LinkedHashMap<>(); diff --git a/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/model/CoverageData.java b/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/model/CoverageData.java index 403d682859c..13bfeb4f80d 100644 --- a/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/model/CoverageData.java +++ b/catalog/camel-route-parser/src/main/java/org/apache/camel/parser/model/CoverageData.java @@ -23,10 +23,11 @@ public class CoverageData { private final String node; private final int count; + private String routeId; public CoverageData(String node, int count) { - this.count = count; this.node = node; + this.count = count; } public String getNode() { @@ -36,4 +37,12 @@ public class CoverageData { public int getCount() { return count; } + + public void setRouteId(String routeId) { + this.routeId = routeId; + } + + public String getRouteId() { + return routeId; + } } diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java index 4b3a3c2dbc8..50df46a5730 100644 --- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java +++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java @@ -115,6 +115,10 @@ public final class RouteCoverageXmlParser { ManagedRouteMBean route = camelContext.getCamelContextExtension() .getContextPlugin(ManagedCamelContext.class).getManagedRoute(id); if (route != null) { + String loc = route.getSourceLocationShort(); + if (loc != null) { + el.setAttribute("sourceLocation", loc); + } long total = route.getExchangesTotal(); el.setAttribute("exchangesTotal", Long.toString(total)); long totalTime = route.getTotalProcessingTime();