├── .github ├── CODEOWNERS ├── release-drafter.yml ├── dependabot.yml └── workflows │ ├── release-drafter.yml │ └── jenkins-security-scan.yml ├── .gitignore ├── .mvn ├── maven.config └── extensions.xml ├── src ├── test │ ├── resources │ │ ├── io │ │ │ └── jenkins │ │ │ │ └── plugins │ │ │ │ └── report │ │ │ │ └── jtreg │ │ │ │ └── main │ │ │ │ └── comparator │ │ │ │ ├── dummyJobs │ │ │ │ └── .placeholder │ │ │ │ └── dummyNvr1.xml │ │ └── rhqe.tar.gz │ └── java │ │ └── io │ │ └── jenkins │ │ └── plugins │ │ └── report │ │ └── jtreg │ │ ├── main │ │ └── comparator │ │ │ ├── BuildsTest.java │ │ │ └── PrintTableTest.java │ │ └── JtregReportParserTest.java └── main │ ├── resources │ ├── index.jelly │ └── io │ │ └── jenkins │ │ └── plugins │ │ └── report │ │ └── jtreg │ │ ├── JckReportPublisher │ │ ├── help-rangeAroundAlist.html │ │ ├── help-reportFileGlob.html │ │ ├── help-resultsDenyList.html │ │ ├── help-maxBuilds.html │ │ ├── help-resultsAllowList.html │ │ └── config.jelly │ │ ├── JtregReportPublisher │ │ ├── help-rangeAroundAlist.html │ │ ├── help-reportFileGlob.html │ │ ├── help-resultsDenyList.html │ │ ├── help-maxBuilds.html │ │ ├── help-resultsAllowList.html │ │ └── config.jelly │ │ ├── JckStyles │ │ └── header.jelly │ │ ├── JenkinsReportJckGlobalConfig │ │ ├── config.jelly │ │ └── help-diffToolUrl.html │ │ ├── ReportAction │ │ └── summary.jelly │ │ ├── ReportChartColumn │ │ ├── column.jelly │ │ └── chartLogicColumn.js │ │ └── ReportProjectAction │ │ └── floatingBox.jelly │ ├── java │ └── io │ │ └── jenkins │ │ └── plugins │ │ └── report │ │ └── jtreg │ │ ├── main │ │ ├── comparator │ │ │ ├── listing │ │ │ │ ├── DirListing.java │ │ │ │ ├── ListDirListing.java │ │ │ │ └── FsDirListing.java │ │ │ ├── jobs │ │ │ │ ├── JobsProvider.java │ │ │ │ └── JobsByRegex.java │ │ │ ├── arguments │ │ │ │ ├── Argument.java │ │ │ │ └── ArgumentsDeclaration.java │ │ │ ├── VirtualJobsResults.java │ │ │ ├── VariantComparator.java │ │ │ ├── JobsPrinting.java │ │ │ ├── Options.java │ │ │ ├── HelpMessage.java │ │ │ ├── Builds.java │ │ │ └── FailedTests.java │ │ ├── diff │ │ │ ├── formatters │ │ │ │ ├── HtmlFormatter2.java │ │ │ │ ├── StringMappedFormatter.java │ │ │ │ ├── BasicFormatter.java │ │ │ │ ├── Formatter.java │ │ │ │ ├── PlainFormatter.java │ │ │ │ ├── HtmlFormatter.java │ │ │ │ └── ColorFormatter.java │ │ │ ├── web │ │ │ │ ├── DiffContextExecutingHandler.java │ │ │ │ ├── ContentCopier.java │ │ │ │ ├── ContentReader.java │ │ │ │ ├── ProcessWrapper.java │ │ │ │ └── ComapreContextExecutingHandler.java │ │ │ ├── RecreateJckReportSummaries.java │ │ │ ├── cmdline │ │ │ │ └── Options.java │ │ │ └── RecreateJtregReportSummaries.java │ │ └── Service.java │ │ ├── utils │ │ └── MoreStrings.java │ │ ├── model │ │ ├── ReportFull.java │ │ ├── TestStatus.java │ │ ├── TestOutput.java │ │ ├── ProjectReport.java │ │ ├── Test.java │ │ ├── SuiteTests.java │ │ ├── SuiteTestChanges.java │ │ ├── Suite.java │ │ ├── BuildReport.java │ │ ├── SuitesWithResults.java │ │ ├── Report.java │ │ └── SuiteTestsWithResults.java │ │ ├── JckStyles.java │ │ ├── wrappers │ │ ├── RunWrapper.java │ │ ├── RunWrapperFromDir.java │ │ └── RunWrapperFromRun.java │ │ ├── parsers │ │ └── ReportParser.java │ │ ├── Constants.java │ │ ├── JenkinsReportJckGlobalConfig.java │ │ ├── JckReportPublisher.java │ │ ├── JtregReportPublisher.java │ │ ├── ReportChartColumn.java │ │ ├── ReportParserCallable.java │ │ ├── ReportAction.java │ │ └── BuildReportExtended.java │ └── webapp │ └── jckstyles.css ├── Jenkinsfile ├── LICENSE └── pom.xml /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jenkinsci/report-jtreg-plugin-developers 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /nbproject/ 3 | .idea/ 4 | *.iml 5 | work/ -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Pconsume-incrementals 2 | -Pmight-produce-incrementals 3 | -------------------------------------------------------------------------------- /src/test/resources/io/jenkins/plugins/report/jtreg/main/comparator/dummyJobs/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | _extends: .github 2 | tag-template: report-jtreg-$NEXT_MINOR_VERSION 3 | -------------------------------------------------------------------------------- /src/test/resources/rhqe.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/judovana/jenkins-report-jtreg/master/src/test/resources/rhqe.tar.gz -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
3 | JUnit/XUnit/jtreg/JCK compatible results publisher plugin targeting huge result bases 4 |
5 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JckReportPublisher/help-rangeAroundAlist.html: -------------------------------------------------------------------------------- 1 |
2 | number of points around allowlist (before and after every point) shown in the results 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JtregReportPublisher/help-rangeAroundAlist.html: -------------------------------------------------------------------------------- 1 |
2 | number of points around allowlist (before and after every point) shown in the results 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JckStyles/header.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JckReportPublisher/help-reportFileGlob.html: -------------------------------------------------------------------------------- 1 |
2 | Glob expression to match the report files. Report parser supports *.xml and *.xml.gz files. For example:
3 | report-{runtime,devtools,compiler}.xml.gz
4 |
-------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JckReportPublisher/help-resultsDenyList.html: -------------------------------------------------------------------------------- 1 |
2 | Packages denylisted (java regex, space separated) from being shown in results (to keep zoomed reuslts readable) and/or fitler specific brach. For example:
3 | .*2\.6\.6\.0.*
4 |
-------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JtregReportPublisher/help-reportFileGlob.html: -------------------------------------------------------------------------------- 1 |
2 | Glob expression to match the report archive. Report parser supports *.zip, *.tar, *.tar.gz, *.tar.bz2 and *.tar.xz files. For example:
3 | *.{zip,tar,tar.gz,tar.bz2,tar.xz}
4 |
-------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JtregReportPublisher/help-resultsDenyList.html: -------------------------------------------------------------------------------- 1 |
2 | Packages denylisted (java regex, space separated) from being shown in results (to keep zoomed reuslts readable) and/or fitler specific brach. For example:
3 | .*2\.6\.6\.0.*
4 |
-------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | /* 2 | See the documentation for more options: 3 | https://github.com/jenkins-infra/pipeline-library/ 4 | */ 5 | buildPlugin( 6 | useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests 7 | configurations: [ 8 | [platform: 'linux', jdk: 17], 9 | [platform: 'windows', jdk: 11], 10 | ]) 11 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/listing/DirListing.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator.listing; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | // an interface used for getting jobs from a directory 7 | public interface DirListing { 8 | ArrayList getJobsInDir(); 9 | } 10 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: maven 6 | directory: / 7 | schedule: 8 | interval: monthly 9 | - package-ecosystem: github-actions 10 | directory: / 11 | schedule: 12 | interval: monthly 13 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JckReportPublisher/help-maxBuilds.html: -------------------------------------------------------------------------------- 1 |
2 | "Number of builds to show" say how many graph points are shown in the results.
3 | If you haven't deny-list empty then it'll show same number of points.
4 | If you haven't allow-list empty then it'll show all available points (allow-listed) with limit of number selected. 5 |
6 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JtregReportPublisher/help-maxBuilds.html: -------------------------------------------------------------------------------- 1 |
2 | "Number of builds to show" say how many graph points are shown in the results.
3 | If you haven't deny-list empty then it'll show same number of points.
4 | If you haven't allow-list empty then it'll show all available points (allow-listed) with limit of number selected. 5 |
6 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JckReportPublisher/help-resultsAllowList.html: -------------------------------------------------------------------------------- 1 |
2 | Packages denylisted (java regex, space separated) are shown in results (to allow filtering of individual job IDs) show only specific brach or similarly. For example:
3 | .*2\.6\.6\.0.*
4 | DenyList has always priority over AllowList 5 |
6 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JenkinsReportJckGlobalConfig/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JtregReportPublisher/help-resultsAllowList.html: -------------------------------------------------------------------------------- 1 |
2 | Packages denylisted (java regex, space separated) are shown in results (to allow filtering of individual job IDs) show only specific brach or similarly. For example:
3 | .*2\.6\.6\.0.*
4 | DenyList has always priority over the AllowList 5 |
6 | -------------------------------------------------------------------------------- /.mvn/extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | io.jenkins.tools.incrementals 4 | git-changelist-maven-extension 5 | 1.6 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # Automates creation of Release Drafts using Release Drafter 2 | # More Info: https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | - main 9 | 10 | jobs: 11 | update_release_draft: 12 | runs-on: ubuntu-latest 13 | steps: 14 | # Drafts your next Release notes as Pull Requests are merged into the default branch 15 | - uses: release-drafter/release-drafter@v5 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/ReportAction/summary.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ${it.displayName} 5 | 6 | 7 | 8 | Total: ${report.total}, Error: ${report.error}, Failed: ${report.failed}, Skipped: ${report.notRun}, Passed: ${report.passed} 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/utils/MoreStrings.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.utils; 2 | 3 | public class MoreStrings { 4 | 5 | private MoreStrings() { 6 | } 7 | 8 | public static int compareStrings(String s1, String s2) { 9 | if (s1 != null) { 10 | // if second is null - first one is bigger: 11 | if (s2 == null) { 12 | return 1; 13 | } 14 | // none of them is null, comparing: 15 | return s1.compareTo(s2); 16 | } 17 | // first and second are null - equal: 18 | if (s2 == null) { 19 | return 0; 20 | } 21 | // if we are here - first is null, second is not: 22 | return -1; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/jenkins-security-scan.yml: -------------------------------------------------------------------------------- 1 | # More information about the Jenkins security scan can be found at the developer docs: https://www.jenkins.io/redirect/jenkins-security-scan/ 2 | 3 | name: Jenkins Security Scan 4 | on: 5 | push: 6 | branches: 7 | - "master" 8 | pull_request: 9 | types: [ opened, synchronize, reopened ] 10 | workflow_dispatch: 11 | 12 | permissions: 13 | security-events: write 14 | contents: read 15 | actions: read 16 | 17 | jobs: 18 | security-scan: 19 | uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2 20 | with: 21 | java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate. 22 | java-version: 11 # What version of Java to set up for the build. 23 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/listing/ListDirListing.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator.listing; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | // a class used in tests - instead of getting the jobs from directory, it simulates it by converting ArrayList of strings to files 7 | public class ListDirListing implements DirListing { 8 | private final ArrayList jobs; 9 | 10 | public ListDirListing(ArrayList jobsList) { 11 | ArrayList convertedJobs = new ArrayList<>(); 12 | for (String s : jobsList) { 13 | convertedJobs.add(new File(s)); 14 | } 15 | 16 | this.jobs = convertedJobs; 17 | } 18 | public ArrayList getJobsInDir() { 19 | return jobs; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/jobs/JobsProvider.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator.jobs; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | public interface JobsProvider { 7 | 8 | // returns a list of arguments that the job provider takes/supports 9 | ArrayList getSupportedArgs(); 10 | 11 | // takes an argument name and value (e.g. argument:"--history" value:"10") and parses it 12 | void parseArguments(String argument, String value); 13 | 14 | // adds a list of unfiltered jobs to the provider 15 | void addJobs(ArrayList jobsInDir); 16 | 17 | // filters the jobs from addJobs() by query, regex etc. 18 | void filterJobs(); 19 | 20 | // returns a list of filtered jobs 21 | ArrayList getJobs(); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JckReportPublisher/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JtregReportPublisher/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/webapp/jckstyles.css: -------------------------------------------------------------------------------- 1 | .jck :target { 2 | border: 1px solid red; 3 | border-collapse: collapse; 4 | } 5 | 6 | .jck table { 7 | border: 1px solid black; 8 | text-align: center; 9 | border-collapse: collapse; 10 | } 11 | 12 | .jck th { 13 | font-family: "Consolas", "DejaVu Sans Mono", monospace; 14 | border: 1px solid black; 15 | padding-left: 6pt; 16 | padding-right: 6pt; 17 | vertical-align: top; 18 | } 19 | 20 | .jck td { 21 | font-family: "Consolas", "DejaVu Sans Mono", monospace; 22 | border: 1px solid black; 23 | padding-left: 6pt; 24 | padding-right: 6pt; 25 | padding-top: 2pt; 26 | padding-bottom: 2pt; 27 | vertical-align: top; 28 | } 29 | 30 | .jck li { 31 | font-family: "Consolas", "DejaVu Sans Mono", monospace; 32 | } 33 | 34 | .detailsTableBorder td { 35 | border: 1px solid gray; 36 | text-align: left; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/listing/FsDirListing.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator.listing; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | public class FsDirListing implements DirListing { 7 | private final ArrayList jobsInDir; 8 | 9 | public FsDirListing(String pathToDirWithJobs) { 10 | File[] filesInDir = new File(pathToDirWithJobs).listFiles(); 11 | if (filesInDir == null) { 12 | throw new RuntimeException("The job directory is empty."); 13 | } 14 | 15 | ArrayList foundJobs = new ArrayList<>(); 16 | for (File f : filesInDir) { 17 | if (f.isDirectory()) { 18 | foundJobs.add(f); 19 | } 20 | } 21 | 22 | this.jobsInDir = foundJobs; 23 | } 24 | 25 | public ArrayList getJobsInDir() { 26 | return jobsInDir; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/arguments/Argument.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator.arguments; 2 | 3 | public class Argument { 4 | private final String argumentName; // the name of the argument (example: --path) 5 | private final String helpMessage; // the help for the argument that will be showed in help message 6 | private final String argumentFormat; // the "format/usage" of the argument that will be showed in the help message (example: etc.) 7 | 8 | public Argument(String argumentName, String helpMessage, String argumentFormat) { 9 | this.argumentName = argumentName; 10 | this.helpMessage = helpMessage; 11 | this.argumentFormat = argumentFormat; 12 | } 13 | 14 | public String getName() { 15 | return argumentName; 16 | } 17 | 18 | public String getHelp() { 19 | return helpMessage; 20 | } 21 | 22 | public String getUsage() { 23 | return argumentFormat; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2023 report-jtreg plugin contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/ReportFull.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.model; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | 6 | public class ReportFull extends Report { 7 | 8 | private final List testsList; 9 | 10 | public ReportFull(int testsPassed, int testsNotRun, int testsFailed, int testsError, int testsTotal, List testProblems, List testsList) { 11 | super(testsPassed, testsNotRun, testsFailed, testsError, testsTotal, testProblems); 12 | this.testsList = testsList; 13 | } 14 | 15 | public List getTestsList() { 16 | return testsList; 17 | } 18 | 19 | @Override 20 | public boolean equals(Object o) { 21 | if (this == o) { 22 | return true; 23 | } 24 | if (o == null || getClass() != o.getClass()) { 25 | return false; 26 | } 27 | if (!super.equals(o)) { 28 | return false; 29 | } 30 | ReportFull that = (ReportFull) o; 31 | return Objects.equals(testsList, that.testsList); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return Objects.hash(super.hashCode(), testsList); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "ReportFull{" + "testsList=" + testsList + "} " + super.toString(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/TestStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | public enum TestStatus { 27 | ERROR, FAILED, PASSED, NOT_RUN; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/JckStyles.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | import hudson.Extension; 27 | import hudson.model.PageDecorator; 28 | 29 | @Extension 30 | public class JckStyles extends PageDecorator { 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/wrappers/RunWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.wrappers; 25 | 26 | import java.io.File; 27 | 28 | public interface RunWrapper { 29 | 30 | public File getRoot(); 31 | 32 | public int getNumber(); 33 | 34 | public String getName(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/TestOutput.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.model; 2 | 3 | import java.util.Objects; 4 | 5 | public class TestOutput implements Comparable, java.io.Serializable { 6 | 7 | private final String name; 8 | private final String value; 9 | 10 | public TestOutput(String name, String value) { 11 | this.name = name; 12 | this.value = value; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public String getValue() { 20 | return value; 21 | } 22 | 23 | @Override 24 | public int compareTo(TestOutput o) { 25 | if (this == o) { 26 | return 0; 27 | } 28 | if (o == null) { 29 | return -1; 30 | } 31 | return name.compareTo(o.getName()); 32 | } 33 | 34 | @Override 35 | public boolean equals(Object o) { 36 | if (this == o) { 37 | return true; 38 | } 39 | if (o == null || getClass() != o.getClass()) { 40 | return false; 41 | } 42 | TestOutput that = (TestOutput) o; 43 | return Objects.equals(name, that.name) && Objects.equals(value, that.value); 44 | } 45 | 46 | @Override 47 | public int hashCode() { 48 | 49 | return Objects.hash(name, value); 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "TestOutput{" + "name='" + name + '\'' + ", value='" + value + '\'' + '}'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/parsers/ReportParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.parsers; 25 | 26 | import io.jenkins.plugins.report.jtreg.model.Suite; 27 | import java.nio.file.Path; 28 | 29 | public interface ReportParser extends java.io.Serializable { 30 | 31 | Suite parsePath(Path path); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | final public class Constants { 27 | 28 | public static final String REPORT_JSON = "report.json"; 29 | public static final String REPORT_TESTS_LIST_JSON = "tests-list.json"; 30 | public static final String IRRELEVANT_GLOB_STRING = "report-{runtime,devtools,compiler}.xml.gz"; 31 | public static final double VAGUE_QUERY_THRESHOLD = 0.5; 32 | 33 | public static final int VAGUE_QUERY_LENGTH_THRESHOLD = 4; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/formatters/HtmlFormatter2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.formatters; 25 | 26 | import java.io.PrintStream; 27 | 28 | public class HtmlFormatter2 extends HtmlFormatter { 29 | 30 | public HtmlFormatter2(PrintStream stream) { 31 | super(stream); 32 | } 33 | 34 | @Override 35 | public void small() { 36 | print(""); 37 | clossingBuffer.add(""); 38 | } 39 | 40 | @Override 41 | public void closeBuildsList() { 42 | reset(); 43 | small(); 44 | print(" |x| "); 45 | reset(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/wrappers/RunWrapperFromDir.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.wrappers; 25 | 26 | import java.io.File; 27 | 28 | /** 29 | * 30 | * @author jvanek 31 | */ 32 | public class RunWrapperFromDir implements RunWrapper { 33 | 34 | private final File back; 35 | 36 | public RunWrapperFromDir(File back) { 37 | this.back = back; 38 | } 39 | 40 | @Override 41 | public File getRoot() { 42 | return back.getAbsoluteFile(); 43 | } 44 | 45 | @Override 46 | public int getNumber() { 47 | return Integer.parseInt(back.getName()); 48 | } 49 | 50 | @Override 51 | public String getName() { 52 | return back.getAbsolutePath(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/formatters/StringMappedFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.formatters; 25 | 26 | import java.io.PrintStream; 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | public abstract class StringMappedFormatter extends BasicFormatter { 31 | 32 | protected final Map colors = new HashMap<>(); 33 | 34 | public StringMappedFormatter(PrintStream o) { 35 | super(o); 36 | } 37 | 38 | protected String getColor(SupportedColors color) { 39 | String sc = colors.get(color); 40 | if (sc == null) { 41 | throw new RuntimeException("Unknown color " + color); 42 | } 43 | return sc; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/wrappers/RunWrapperFromRun.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.wrappers; 25 | 26 | import hudson.model.Run; 27 | import java.io.File; 28 | 29 | /** 30 | * 31 | * @author jvanek 32 | */ 33 | public class RunWrapperFromRun implements RunWrapper{ 34 | 35 | private final Run job; 36 | 37 | public RunWrapperFromRun(Run job) { 38 | this.job = job; 39 | } 40 | 41 | @Override 42 | public File getRoot() { 43 | return job.getRootDir(); 44 | } 45 | 46 | @Override 47 | public int getNumber() { 48 | return job.getNumber(); 49 | } 50 | 51 | @Override 52 | public String getName() { 53 | return job.getDisplayName(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/JenkinsReportJckGlobalConfig.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg; 2 | 3 | 4 | import net.sf.json.JSONObject; 5 | 6 | import org.kohsuke.stapler.DataBoundConstructor; 7 | import org.kohsuke.stapler.DataBoundSetter; 8 | import org.kohsuke.stapler.StaplerRequest; 9 | 10 | import java.util.logging.Logger; 11 | 12 | import hudson.Extension; 13 | import jenkins.model.GlobalConfiguration; 14 | 15 | @Extension 16 | public class JenkinsReportJckGlobalConfig extends GlobalConfiguration { 17 | private static Logger logger = Logger.getLogger(JenkinsReportJckGlobalConfig.class.getName()); 18 | 19 | String diffToolUrl; 20 | 21 | public static JenkinsReportJckGlobalConfig getInstance() { 22 | return GlobalConfiguration.all().get(JenkinsReportJckGlobalConfig.class); 23 | } 24 | 25 | public static String getGlobalDiffUrl() { 26 | return getInstance().getDiffToolUrl(); 27 | } 28 | 29 | public static String getGlobalDiffUrlMissing() { 30 | return "Difftool url is not set"; 31 | } 32 | 33 | public static boolean isGlobalDiffUrl() { 34 | return getInstance().isDiffToolUrlSet(); 35 | } 36 | 37 | public boolean isDiffToolUrlSet() { 38 | return diffToolUrl != null && !diffToolUrl.trim().isEmpty(); 39 | } 40 | 41 | public String getDiffToolUrl() { 42 | return diffToolUrl; 43 | } 44 | 45 | @DataBoundSetter 46 | public void setDiffToolUrl(String diffToolUrl) { 47 | this.diffToolUrl = diffToolUrl; 48 | } 49 | 50 | @DataBoundConstructor 51 | public JenkinsReportJckGlobalConfig(String diffToolUrl) { 52 | this.diffToolUrl = diffToolUrl; 53 | } 54 | 55 | public JenkinsReportJckGlobalConfig() { 56 | load(); 57 | } 58 | 59 | 60 | @Override 61 | public boolean configure(StaplerRequest req, JSONObject json) throws FormException { 62 | req.bindJSON(this, json); 63 | save(); 64 | return super.configure(req, json); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/web/DiffContextExecutingHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.web; 25 | 26 | import java.io.File; 27 | import java.io.IOException; 28 | import java.io.UnsupportedEncodingException; 29 | 30 | import io.jenkins.plugins.report.jtreg.main.diff.cmdline.Arguments; 31 | 32 | public class DiffContextExecutingHandler extends ContextExecutingHandler { 33 | 34 | public DiffContextExecutingHandler(File targetProgram) throws IOException { 35 | super(targetProgram); 36 | } 37 | @Override 38 | protected String loadDifTemplate() throws IOException { 39 | return loadTemplate("/io/jenkins/plugins/report/jtreg/main/web/diff.html"); 40 | } 41 | 42 | @Override 43 | protected String pritnHelp() throws UnsupportedEncodingException { 44 | return Arguments.printHelp(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/ProjectReport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import java.util.List; 27 | 28 | public class ProjectReport implements java.io.Serializable { 29 | 30 | private final List reports; 31 | private final List improvements; 32 | private final List regressions; 33 | 34 | public ProjectReport(List reports, List improvements, List regressions) { 35 | this.reports = reports; 36 | this.improvements = improvements; 37 | this.regressions = regressions; 38 | } 39 | 40 | public List getReports() { 41 | return reports; 42 | } 43 | 44 | public List getImprovements() { 45 | return improvements; 46 | } 47 | 48 | public List getRegressions() { 49 | return regressions; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/report/jtreg/main/comparator/BuildsTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.diff.cmdline.JobsRecognition; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | 9 | 10 | 11 | public class BuildsTest { 12 | 13 | private static File changelogFile; 14 | 15 | @org.junit.BeforeClass 16 | public static void createChangelogFile() throws IOException { 17 | File tmpdir = Files.createTempDirectory("reportJtregBuildTestDir").toFile(); 18 | changelogFile = JobsRecognition.creteChangelogFile(tmpdir); 19 | byte[] orig = BuildsTest.class.getResourceAsStream("/io/jenkins/plugins/report/jtreg/main/comparator/dummyNvr1.xml").readAllBytes(); 20 | Files.write(changelogFile.toPath(), orig); 21 | } 22 | 23 | @org.junit.Test 24 | public void checkForNvrTest() { 25 | boolean b = Builds.checkForNvr(new File("unused in this call"), "*"); 26 | org.junit.Assert.assertTrue(b); 27 | b = Builds.checkForNvr(changelogFile.getParentFile(), "blah"); 28 | org.junit.Assert.assertFalse(b); 29 | b = Builds.checkForNvr(changelogFile.getParentFile(), "{blah}"); 30 | org.junit.Assert.assertFalse(b); 31 | b = Builds.checkForNvr(changelogFile.getParentFile(), "{blah, bleh}"); 32 | org.junit.Assert.assertFalse(b); 33 | b = Builds.checkForNvr(changelogFile.getParentFile(), "java-17-openjdk-portable-17.0.6.0.10-6.el7openjdkportable"); 34 | org.junit.Assert.assertTrue(b); 35 | b = Builds.checkForNvr(changelogFile.getParentFile(), "{blah,java-17-openjdk-portable-17.0.6.0.10-6.el7openjdkportable, bleh}"); 36 | org.junit.Assert.assertTrue(b); 37 | b = Builds.checkForNvr(changelogFile.getParentFile(), "java-17-openjdk-portable-17.0.6.0.10-6"); 38 | org.junit.Assert.assertFalse(b); 39 | b = Builds.checkForNvr(changelogFile.getParentFile(), "java-17-openjdk-portable-17.0.6.0.10-6.*"); 40 | org.junit.Assert.assertTrue(b); 41 | b = Builds.checkForNvr(changelogFile.getParentFile(), "{blah,java-17-openjdk-portable-17.0.6.0.10-6.*, bleh}"); 42 | org.junit.Assert.assertTrue(b); 43 | 44 | 45 | 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/formatters/BasicFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.formatters; 25 | 26 | import java.io.PrintStream; 27 | 28 | public abstract class BasicFormatter implements Formatter { 29 | 30 | protected PrintStream o; 31 | 32 | public BasicFormatter(PrintStream o) { 33 | this.o = o; 34 | } 35 | 36 | @Override 37 | public void print(String s) { 38 | o.print(s); 39 | } 40 | 41 | @Override 42 | public void println(String s) { 43 | o.println(s); 44 | } 45 | 46 | @Override 47 | public void println() { 48 | println(""); 49 | } 50 | 51 | @Override 52 | public void closeBuildsList() { 53 | println(""); 54 | reset(); 55 | } 56 | 57 | @Override 58 | public void small(){ 59 | 60 | } 61 | 62 | @Override 63 | public void pre(){ 64 | 65 | } 66 | 67 | @Override 68 | public void preClose(){ 69 | 70 | } 71 | 72 | @Override 73 | public void printTable(String[][] table, int rowSize, int columnSize) { 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/JenkinsReportJckGlobalConfig/help-diffToolUrl.html: -------------------------------------------------------------------------------- 1 |
2 | Jenkins report jck plugin is designed to work with egtremly huge datasets 100 000 items and up.
3 | To do this properly, some queries are not available on project page, but were moved to external cmdline tool/service
4 | That are io.jenkins.plugins.report.jtreg.main.diff.CompareBuilds and io.jenkins.plugins.report.jtreg.main.Service classes
5 | Unluckily, those were never designed with security in mind, were just needed "yesterday", so:
6 |
  • They reside in codebase of plugin
  • 7 |
  • the cli is superpowerful
  • 8 |
  • The http service is actually just wrapping the cli (really, it literaly calls the launcher, see lower)
  • 9 |
  • default port is 9090
  • 10 |
  • -Djenkins_home=$jenkins_main_home property is mandatory for cli (and thus indirectly for service)
  • 11 |
    so... 12 |
  • they need all jenkins jars on classpath
  • 13 |
  • you need shell (or other) executbale wrapper around the CLI to set up CP and actually start the application
  • 14 |
  • the sevice is then consuming this lancher and jsut redirects stdout/err. eg:
  • 15 |
  • shell.sh: /opt/jdk/bin/java -cp $CP -Djenkins_home=$jenkins_main_home 16 | io.jenkins.plugins.report.jtreg.main.diff.CompareBuilds $@
  • 17 |
  • Where the CP contains jars from unpacked jenkins.war and jenkins report pluginwith depndencies
  • 18 |
  • service.sh: /opt/jdk/bin/java io.jenkins.plugins.report.jtreg.main.Service 19 | /path/to/shel.sh customPort
  • 20 |
  • this field: some_url:customPort, usually, if it is on same machine, which it usually is, jenkins_url but on 9090 or custom port
  • 21 |
    22 |
  • There is work in progress ot extract the cli and service properly, and to do new cli
  • 23 |
  • if you include diff url, new links will appear in the report
  • 24 |
  • Those links will pre-fill service api so you can easily place advanced queries
  • 25 | Note, that jar with dependecies is default target for project. Plugin is built as -Phpi 26 |

    See jenkins-report-jck/blob/master/README.md

    27 |
    28 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/jobs/JobsByRegex.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator.jobs; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.comparator.arguments.Argument; 4 | import io.jenkins.plugins.report.jtreg.main.comparator.arguments.ArgumentsDeclaration; 5 | 6 | import java.io.File; 7 | import java.util.ArrayList; 8 | 9 | public class JobsByRegex implements JobsProvider { 10 | public static final Argument regexArg = new Argument("--regex", "A regular expression to filter the jobs by their names.", " "); 11 | 12 | 13 | private String regexString; 14 | private boolean forceVague; 15 | private ArrayList jobsInDir; 16 | private ArrayList matchedJobs; 17 | 18 | public JobsByRegex() { 19 | this.regexString = ""; 20 | this.forceVague = false; 21 | this.jobsInDir = new ArrayList<>(); 22 | this.matchedJobs = new ArrayList<>(); 23 | } 24 | 25 | public ArrayList getSupportedArgs() { 26 | ArrayList supportedArgs = new ArrayList<>(); 27 | supportedArgs.add(regexArg.getName()); 28 | return supportedArgs; 29 | } 30 | 31 | public void parseArguments(String argument, String value) { 32 | if (argument.equals(regexArg.getName())) { 33 | this.regexString = value; 34 | } else if (argument.equals(ArgumentsDeclaration.forceArg.getName())) { 35 | this.forceVague = true; 36 | } else { 37 | throw new RuntimeException("JobsByRegex got an unexpected argument."); 38 | } 39 | } 40 | 41 | public void addJobs(ArrayList jobsInDir) { 42 | this.jobsInDir = jobsInDir; 43 | } 44 | 45 | public void filterJobs() { 46 | // check if the regex is not too vague (has only .*) 47 | if (this.regexString.matches("^(\\.\\*)*$") && !this.forceVague) { 48 | throw new RuntimeException("The regular expression is too vague (contains only .*), run with --force to continue anyway."); 49 | } 50 | 51 | this.matchedJobs = new ArrayList<>(); 52 | for (File job : this.jobsInDir) { 53 | if (job.getName().matches(this.regexString)) { 54 | this.matchedJobs.add(job); 55 | } 56 | } 57 | } 58 | 59 | public ArrayList getJobs() { 60 | return matchedJobs; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/Test.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.model; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | 6 | import io.jenkins.plugins.report.jtreg.utils.MoreStrings; 7 | 8 | public class Test implements Comparable, java.io.Serializable { 9 | 10 | private final String name; 11 | private final TestStatus status; 12 | private final String statusLine; 13 | private final List outputs; 14 | 15 | public Test(String name, TestStatus status, String statusLine, List outputs) { 16 | this.name = name; 17 | this.status = status; 18 | this.statusLine = statusLine; 19 | this.outputs = outputs; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public TestStatus getStatus() { 27 | return status; 28 | } 29 | 30 | public String getStatusLine() { 31 | return statusLine; 32 | } 33 | 34 | public List getOutputs() { 35 | return outputs; 36 | } 37 | 38 | @Override 39 | public int compareTo(Test o) { 40 | return MoreStrings.compareStrings(name, o.getName()); 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) { 46 | return true; 47 | } 48 | if (o == null || getClass() != o.getClass()) { 49 | return false; 50 | } 51 | Test test = (Test) o; 52 | return Objects.equals(name, test.name) && status == test.status && Objects.equals(statusLine, test.statusLine) && Objects.equals(outputs, test.outputs); 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | 58 | return Objects.hash(name, status, statusLine, outputs); 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "Test{" + "name='" + name + '\'' + ", status=" + status + ", statusLine='" + statusLine + '\'' + ", " + 64 | "outputs=" + outputs + '}'; 65 | } 66 | 67 | private static String createDiffUrl() { 68 | return SuiteTestsWithResults.getDiffServer() + "?generated-part=+-view%3Dall-tests+++-output%3Dhtml++-fill++"; 69 | } 70 | 71 | 72 | public String getTrackingUrl(String job) { 73 | return (createDiffUrl()+"&custom-part=-track%3D"+name+"++"+job+"++0+-365").replaceAll("#", "%23"); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/formatters/Formatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.formatters; 25 | 26 | public interface Formatter { 27 | 28 | public enum SupportedColors { 29 | Default, 30 | Black, 31 | Red, 32 | Green, 33 | Yellow, 34 | Blue, 35 | Magenta, 36 | Cyan, 37 | LightRed, 38 | LightGreen, 39 | LightYellow, 40 | LightBlue, 41 | LightMagenta, 42 | LightCyan, 43 | 44 | } 45 | 46 | public void print(String s); 47 | 48 | public void println(); 49 | 50 | public void println(String s); 51 | 52 | public void startBold(); 53 | 54 | public void startColor(SupportedColors color); 55 | 56 | public void reset(); 57 | 58 | public void initDoc(); 59 | 60 | public void closeDoc(); 61 | 62 | public void startTitle4(); 63 | 64 | public void startTitle3(); 65 | 66 | public void startTitle2(); 67 | 68 | public void startTitle1(); 69 | 70 | public void closeBuildsList(); 71 | public void small(); 72 | public void pre(); 73 | public void preClose(); 74 | 75 | public void printTable(String[][] table, int rowSize, int columnSize); 76 | } 77 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/ReportChartColumn/column.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 |
    11 | 12 | No JCK results yet 13 | 14 | 15 | 18 | 19 |
    20 | 21 |
    22 | 25 | 26 | 31 | 32 | 37 | 38 | 43 |
    44 |
    45 | 46 |
    47 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/web/ContentCopier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.web; 25 | 26 | import java.io.BufferedReader; 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.io.InputStreamReader; 30 | import java.io.Writer; 31 | 32 | /** 33 | * Class to read and resend content of stdout/stderr of process. 34 | */ 35 | class ContentCopier implements Runnable { 36 | 37 | private final InputStream is; 38 | private final Writer w; 39 | 40 | public ContentCopier(InputStream is, Writer target) throws IOException { 41 | this.is = is; 42 | this.w = target; 43 | } 44 | 45 | @Override 46 | public void run() { 47 | try { 48 | runImpl(); 49 | } catch (Exception ex) { 50 | throw new RuntimeException(ex); 51 | } 52 | } 53 | 54 | private void runImpl() throws IOException { 55 | try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) { 56 | while (true) { 57 | String line = br.readLine(); 58 | if (line == null) { 59 | break; 60 | } 61 | w.write(line + "\n"); 62 | } 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/SuiteTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import io.jenkins.plugins.report.jtreg.utils.MoreStrings; 27 | 28 | import java.util.List; 29 | import java.util.Objects; 30 | 31 | public class SuiteTests implements Comparable, java.io.Serializable { 32 | 33 | private final String name; 34 | private final List tests; 35 | 36 | public SuiteTests(String name, List tests) { 37 | this.name = name; 38 | this.tests = tests; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public List getTests() { 46 | return tests; 47 | } 48 | 49 | @Override 50 | public int compareTo(SuiteTests o) { 51 | return MoreStrings.compareStrings(name, o.getName()); 52 | } 53 | 54 | @Override 55 | public boolean equals(Object o) { 56 | if (this == o) return true; 57 | if (o == null || getClass() != o.getClass()) return false; 58 | SuiteTests that = (SuiteTests) o; 59 | return Objects.equals(getName(), that.getName()); 60 | } 61 | 62 | @Override 63 | public int hashCode() { 64 | return Objects.hash(getName()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/web/ContentReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.web; 25 | 26 | import java.io.BufferedReader; 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.io.InputStreamReader; 30 | 31 | /** 32 | * Class to read and save content of stdout/stderr of process. 33 | */ 34 | class ContentReader implements Runnable { 35 | 36 | StringBuilder sb = new StringBuilder(); 37 | private final InputStream is; 38 | 39 | public String getContent() { 40 | return sb.toString(); 41 | } 42 | 43 | public ContentReader(InputStream is) throws IOException { 44 | this.is = is; 45 | } 46 | 47 | @Override 48 | public void run() { 49 | try { 50 | runImpl(); 51 | } catch (Exception ex) { 52 | throw new RuntimeException(ex); 53 | } 54 | } 55 | 56 | private void runImpl() throws IOException { 57 | try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) { 58 | while (true) { 59 | String line = br.readLine(); 60 | if (line == null) { 61 | break; 62 | } 63 | sb.append(line).append("\n"); 64 | } 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/VirtualJobsResults.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.Formatter; 4 | import org.w3c.dom.Document; 5 | import javax.xml.parsers.DocumentBuilder; 6 | import javax.xml.parsers.DocumentBuilderFactory; 7 | import java.io.File; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | 12 | public class VirtualJobsResults { 13 | private static final List results = Arrays.asList("SUCCESS", "UNSTABLE", "FAILURE", "ABORTED", "RUNNING?"); 14 | 15 | private static String getBuildResult(File build) { 16 | Document doc = null; 17 | try { 18 | File buildXml = new File(build.getAbsolutePath() + "/build.xml"); 19 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 20 | DocumentBuilder builder = factory.newDocumentBuilder(); 21 | doc = builder.parse(buildXml); 22 | doc.getDocumentElement().normalize(); 23 | } catch (Exception e) { 24 | e.printStackTrace(); 25 | } 26 | 27 | if (doc == null) { 28 | return "RUNNING?"; 29 | } 30 | 31 | try { 32 | return doc.getElementsByTagName("result").item(0) 33 | .getChildNodes().item(0) 34 | .getNodeValue(); 35 | } catch (Exception e) { 36 | return "RUNNING?"; 37 | } 38 | } 39 | 40 | public static void printVirtualTable(ArrayList buildsToCompare, Formatter formatter) { 41 | formatter.startBold(); 42 | formatter.println("Virtual builds' results table:"); 43 | formatter.println(); 44 | formatter.reset(); 45 | 46 | String[][] table = new String[results.size() + 1][buildsToCompare.size() + 1]; 47 | 48 | // first column definitions 49 | for (int i = 1; i <= results.size(); i++) { 50 | table[i][0] = results.get(i - 1); 51 | } 52 | 53 | for (int i = 1; i <= buildsToCompare.size(); i++) { 54 | File build = buildsToCompare.get(i - 1); 55 | table[0][i] = Builds.getJobName(build) 56 | + " - build:" + Builds.getBuildNumber(build) 57 | + " - nvr:" + Builds.getNvr(build); 58 | 59 | String result = getBuildResult(build); 60 | table[results.indexOf(result) + 1][i] = "X"; 61 | } 62 | 63 | formatter.printTable(table, results.size() + 1, buildsToCompare.size() + 1); 64 | } 65 | } -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/SuiteTestChanges.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import java.util.List; 27 | 28 | public class SuiteTestChanges implements java.io.Serializable { 29 | 30 | private final String name; 31 | private final List failures; 32 | private final List errors; 33 | private final List fixes; 34 | private final List added; 35 | private final List removed; 36 | 37 | public SuiteTestChanges(String name, List failures, List errors, List fixes, List added, List removed) { 38 | this.name = name; 39 | this.failures = failures; 40 | this.errors = errors; 41 | this.fixes = fixes; 42 | this.added = added; 43 | this.removed = removed; 44 | } 45 | 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | public List getAdded() { 51 | return added; 52 | } 53 | 54 | public List getRemoved() { 55 | return removed; 56 | } 57 | 58 | public List getFailures() { 59 | return failures; 60 | } 61 | 62 | public List getErrors() { 63 | return errors; 64 | } 65 | 66 | public List getFixes() { 67 | return fixes; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/report/jtreg/JtregReportParserTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg; 2 | 3 | import io.jenkins.plugins.report.jtreg.model.TestOutput; 4 | import org.junit.Assert; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.nio.file.Files; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | 14 | import io.jenkins.plugins.report.jtreg.model.Suite; 15 | import io.jenkins.plugins.report.jtreg.model.Test; 16 | import io.jenkins.plugins.report.jtreg.parsers.JtregReportParser; 17 | 18 | public class JtregReportParserTest { 19 | 20 | private final static String rhqeFileName = "rhqe.tar.gz"; 21 | 22 | @org.junit.Test 23 | public void parseRhqeTest() throws IOException { 24 | String tarball = "src/test/resources/" + rhqeFileName; //jtreg arser currently depends on file, and that file have to be tarball with named xmls 25 | final JtregReportParser parser = new JtregReportParser(); 26 | Suite actualReport = parser.parsePath(new File(tarball).toPath()); 27 | List failures = actualReport.getReport().getTestProblems(); 28 | Assert.assertEquals(2, failures.size()); 29 | List outputs1 = failures.get(0).getOutputs(); 30 | Assert.assertEquals(2, outputs1.size()); 31 | Assert.assertTrue(outputs1.get(1).getValue().contains("grep")); 32 | Assert.assertTrue(outputs1.get(1).getValue().contains("Pack")); 33 | List outputs2 = failures.get(1).getOutputs(); 34 | Assert.assertEquals(2, outputs2.size()); 35 | Assert.assertTrue(outputs2.get(1).getValue().contains("head")); 36 | Assert.assertTrue(outputs2.get(1).getValue().contains("Attempt")); 37 | 38 | File tmpJMainDir = File.createTempFile("jtregJenkinsJckPlugin","test.json"); 39 | tmpJMainDir.delete(); 40 | tmpJMainDir.mkdir(); 41 | tmpJMainDir.deleteOnExit(); 42 | File tmpDir2 = new File(tmpJMainDir, "jobs/builds/5"); 43 | tmpDir2.mkdirs(); 44 | File tmpJson = new File(tmpDir2,"test.json"); 45 | JtregReportPublisher jp = new JtregReportPublisher("notImportantNow"); 46 | jp.storeFailuresSummary(Arrays.asList(actualReport), tmpJson); 47 | String s = Files.readAllLines(tmpJson.toPath()).stream().collect(Collectors.joining("\n")); 48 | Assert.assertTrue(s.contains("grep")); 49 | Assert.assertTrue(s.contains("Pack")); 50 | Assert.assertTrue(s.contains("head")); 51 | Assert.assertTrue(s.contains("Attempt")); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/VariantComparator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.comparator.arguments.ArgumentsParsing; 4 | import io.jenkins.plugins.report.jtreg.main.comparator.listing.DirListing; 5 | import io.jenkins.plugins.report.jtreg.main.comparator.listing.FsDirListing; 6 | 7 | import java.io.File; 8 | import java.util.ArrayList; 9 | 10 | public class VariantComparator { 11 | public static void main(String[] args) throws Exception { 12 | Options options = ArgumentsParsing.parse(args); 13 | if(options.isDie()) { 14 | return; 15 | } 16 | 17 | DirListing dl = new FsDirListing(options.getJobsPath()); 18 | 19 | // add the jobs to the provider and filter them 20 | options.getJobsProvider().addJobs(dl.getJobsInDir()); 21 | options.getJobsProvider().filterJobs(); 22 | 23 | ArrayList buildsToCompare = new ArrayList<>(); 24 | for (File job : options.getJobsProvider().getJobs()) { 25 | ArrayList builds = Builds.getBuilds(job, options.isSkipFailed(), options.getNvrQuery(), 26 | options.getNumberOfBuilds(), options.isUseDefaultBuild(), options.getFormatter()); 27 | buildsToCompare.addAll(builds); 28 | } 29 | 30 | if (buildsToCompare.size() != 0) { 31 | // do the chosen operation 32 | if (options.getOperation() == Options.Operations.List || options.getOperation() == Options.Operations.Compare) { 33 | FailedTests.printFailedTable( 34 | FailedTests.createFailedMap(buildsToCompare, options.isOnlyVolatile(), options.getExactTestsRegex(), options.getFormatter()), 35 | options.getOperation(), options.getFormatter()); 36 | } else if (options.getOperation() == Options.Operations.Enumerate) { 37 | JobsPrinting.printVariants(options.getJobsProvider().getJobs(), options.getFormatter()); 38 | } else if (options.getOperation() == Options.Operations.Print) { 39 | JobsPrinting.printJobs(options.getJobsProvider().getJobs(), options.isSkipFailed(), options.getNvrQuery(), 40 | options.getNumberOfBuilds(), options.getFormatter(), options.isUseDefaultBuild()); 41 | } 42 | 43 | // print virtual table 44 | if (options.isPrintVirtual()) { 45 | options.getFormatter().println(); 46 | VirtualJobsResults.printVirtualTable(buildsToCompare, options.getFormatter()); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/Suite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import io.jenkins.plugins.report.jtreg.utils.MoreStrings; 27 | 28 | import java.util.Objects; 29 | 30 | public class Suite implements Comparable, java.io.Serializable { 31 | 32 | private final String name; 33 | private final Report report; 34 | 35 | public Suite(String name, Report report) { 36 | this.name = name; 37 | this.report = report; 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public Report getReport() { 45 | return report; 46 | } 47 | 48 | @Override 49 | public int compareTo(Suite o) { 50 | return MoreStrings.compareStrings(name, o.getName()); 51 | } 52 | 53 | @Override 54 | public boolean equals(Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | Suite suite = (Suite) o; 62 | return Objects.equals(name, suite.name) && Objects.equals(report, suite.report); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(name, report); 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return "Suite{" + "name='" + name + '\'' + ", report=" + report + '}'; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/web/ProcessWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.web; 25 | 26 | import java.io.IOException; 27 | import java.io.Writer; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | /** 32 | * 33 | * @author jvanek 34 | */ 35 | public class ProcessWrapper implements Runnable { 36 | 37 | private final List cmds; 38 | private final Writer out; 39 | private String errorResult; 40 | 41 | public ProcessWrapper(final Writer output,final String[] cmds) { 42 | this.cmds = Arrays.asList(cmds); 43 | this.out = output; 44 | } 45 | 46 | @Override 47 | public void run() { 48 | try { 49 | runImpl(); 50 | } catch (Exception ex) { 51 | throw new RuntimeException(ex); 52 | } 53 | } 54 | 55 | private void runImpl() throws IOException, InterruptedException { 56 | ProcessBuilder pb = new ProcessBuilder(cmds); 57 | Process p = pb.start(); 58 | ContentCopier sout = new ContentCopier(p.getInputStream(), out); 59 | ContentReader serr = new ContentReader(p.getErrorStream()); 60 | new Thread(sout).start(); 61 | new Thread(serr).start(); 62 | Thread.sleep(100); 63 | p.waitFor(); 64 | Thread.sleep(100); 65 | errorResult = serr.getContent(); 66 | } 67 | 68 | public String getErrorResult() { 69 | return errorResult; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/JobsPrinting.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.Formatter; 4 | 5 | import java.io.File; 6 | import java.util.ArrayList; 7 | 8 | public class JobsPrinting { 9 | // print all matched jobs and their matched builds 10 | public static void printJobs(ArrayList matchedJobs, boolean skipFailed, String nvrQuery, int numberOfBuilds, Formatter formatter, boolean useDefaultBuild) { 11 | for (File job : matchedJobs) { 12 | formatter.startBold(); 13 | formatter.println(job.getName() + ":"); 14 | formatter.reset(); 15 | ArrayList jobBuilds = Builds.getBuilds(job, skipFailed, nvrQuery, numberOfBuilds, useDefaultBuild, formatter); 16 | for (File build : jobBuilds) { 17 | formatter.print("\t"); 18 | formatter.startColor(Formatter.SupportedColors.LightBlue); 19 | formatter.print("build:"); 20 | formatter.reset(); 21 | formatter.print(Builds.getBuildNumber(build)); 22 | formatter.print(" - "); 23 | formatter.startColor(Formatter.SupportedColors.LightBlue); 24 | formatter.print("nvr: "); 25 | formatter.reset(); 26 | formatter.println(Builds.getNvr(build)); 27 | } 28 | } 29 | } 30 | 31 | // print the available variants of all jobs (meant to be used with query) 32 | public static void printVariants(ArrayList matchedJobs, Formatter formatter) { 33 | int maxLength = 0; 34 | ArrayList splitJobs = new ArrayList<>(); 35 | 36 | for (File job : matchedJobs) { 37 | String[] splitJob = job.getName().split("[.-]"); 38 | splitJobs.add(splitJob); 39 | if (splitJob.length > maxLength) { 40 | maxLength = splitJob.length; 41 | } 42 | } 43 | 44 | for (int i = 0; i < maxLength; i++) { 45 | ArrayList variantList = new ArrayList<>(); 46 | for (String[] job : splitJobs) { 47 | 48 | // checks the variant with query string and adds only non-duplicate 49 | if (job.length > i && !variantList.contains(job[i])) { 50 | variantList.add(job[i]); 51 | } 52 | } 53 | formatter.startBold(); 54 | formatter.print(i + 1 + ") "); 55 | formatter.reset(); 56 | for (String variant : variantList) { 57 | formatter.print(variant + ", "); 58 | } 59 | formatter.println(""); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/ReportProjectAction/floatingBox.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 |

    Number of Failures: ${action.displayName}

    4 |
    5 |

    Number of Tests total: ${action.displayName}

    6 |
    7 |

    Regressions: ${action.displayName}

    8 |
    9 | 10 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 47 |
    48 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/JckReportPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | import hudson.Extension; 27 | import hudson.model.AbstractProject; 28 | import io.jenkins.plugins.report.jtreg.parsers.JckReportParser; 29 | import io.jenkins.plugins.report.jtreg.parsers.ReportParser; 30 | import hudson.tasks.BuildStepDescriptor; 31 | import hudson.tasks.Publisher; 32 | import org.kohsuke.stapler.DataBoundConstructor; 33 | 34 | public class JckReportPublisher extends AbstractReportPublisher { 35 | 36 | @DataBoundConstructor 37 | public JckReportPublisher(String reportFileGlob) { 38 | super(reportFileGlob); 39 | } 40 | 41 | @Override 42 | protected String defaultReportFileGlob() { 43 | return "glob:*.{xml,xml.gz}"; 44 | } 45 | 46 | @Override 47 | protected String prefix() { 48 | return "jck"; 49 | } 50 | 51 | @Override 52 | protected ReportParser createReportParser() { 53 | return new JckReportParser(); 54 | } 55 | 56 | @Override 57 | public BuildStepDescriptor getDescriptor() { 58 | return DESCRIPTOR; 59 | } 60 | 61 | @Extension 62 | public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); 63 | 64 | public static class DescriptorImpl extends BuildStepDescriptor { 65 | 66 | @Override 67 | public String getDisplayName() { 68 | return "JCK Report"; 69 | } 70 | 71 | @Override 72 | public boolean isApplicable(Class jobType) { 73 | return true; 74 | } 75 | 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/JtregReportPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | import hudson.Extension; 27 | import hudson.model.AbstractProject; 28 | import io.jenkins.plugins.report.jtreg.parsers.JtregReportParser; 29 | import io.jenkins.plugins.report.jtreg.parsers.ReportParser; 30 | import hudson.tasks.BuildStepDescriptor; 31 | import hudson.tasks.Publisher; 32 | import org.kohsuke.stapler.DataBoundConstructor; 33 | 34 | public class JtregReportPublisher extends AbstractReportPublisher { 35 | 36 | @DataBoundConstructor 37 | public JtregReportPublisher(String reportFileGlob) { 38 | super(reportFileGlob); 39 | } 40 | 41 | public static final String sfxs = "zip,tar,tar.gz,tar.bz2,tar.xz"; 42 | 43 | public static boolean isJtregArchive(String s){ 44 | String[] ss = sfxs.split(","); 45 | for (String s1 : ss) { 46 | if (s.endsWith(s1)){ 47 | return true; 48 | } 49 | } 50 | return false; 51 | } 52 | 53 | @Override 54 | protected String defaultReportFileGlob() { 55 | return "glob:*.{"+sfxs+"}"; 56 | } 57 | 58 | @Override 59 | protected ReportParser createReportParser() { 60 | return new JtregReportParser(); 61 | } 62 | 63 | @Override 64 | protected String prefix() { 65 | return "jtreg"; 66 | } 67 | 68 | @Override 69 | public BuildStepDescriptor getDescriptor() { 70 | return DESCRIPTOR; 71 | } 72 | 73 | @Extension 74 | public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); 75 | 76 | public static class DescriptorImpl extends BuildStepDescriptor { 77 | 78 | @Override 79 | public String getDisplayName() { 80 | return "JTreg Report"; 81 | } 82 | 83 | @Override 84 | public boolean isApplicable(Class jobType) { 85 | return true; 86 | } 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/arguments/ArgumentsDeclaration.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator.arguments; 2 | 3 | public final class ArgumentsDeclaration { 4 | //public static final Argument exampleArg = new Argument("--argument-name", "The help message of this argument that will be shown with --help.", "") 5 | public static final Argument helpArg = new Argument("--help", "Print this help message.", ""); 6 | public static final Argument listArg = new Argument("--list", "Print a table of matched jobs with their builds and the tests that failed in the build.", ""); 7 | public static final Argument enumerateArg = new Argument("--enumerate", "Print lists of all variants of jobs (that match the rest of arguments).", ""); 8 | public static final Argument compareArg = new Argument("--compare", "Print a table of all failed tests (of matched job builds) and the builds where they failed.", ""); 9 | public static final Argument printArg = new Argument("--print", "Print all jobs and their builds that match the rest of arguments, without actually doing any operation on the builds or tests.", ""); 10 | public static final Argument virtualArg = new Argument("--virtual", "Print a table of all matched jobs' builds and their result (e.g. SUCCESS, UNSTABLE, etc.). Can be used as standalone operation or combined with any other operation. Probably should be run with --skip-failed=false switch.", ""); 11 | public static final Argument pathArg = new Argument("--path", "A system path to a directory with your jenkins jobs. This argument is mandatory", " "); 12 | public static final Argument nvrArg = new Argument("--nvr", "To specify what builds to take (only builds with specified NVRs). The syntax is described below.", " "); 13 | public static final Argument historyArg = new Argument("--history", "To specify the maximum number of builds to look in.", " "); 14 | public static final Argument skipFailedArg = new Argument("--skip-failed", "Specify whether the comparator should skip failed tests (only take successful and unstable) or take all. The default value is true.", "="); 15 | public static final Argument forceArg = new Argument("--force", "Used for forcing vague requests, that could potentially take a long time.", ""); 16 | public static final Argument onlyVolatileArg = new Argument("--only-volatile", "Specify true to show only non stable tests with the arguments list and compare (shows only tests, that are NOT failed everywhere). The default value is false.", "="); 17 | public static final Argument exactTestsArg = new Argument("--exact-tests", "Specify (with regex) the exact tests to show only. The rest of tests will be ignored.", " "); 18 | public static final Argument formattingArg = new Argument("--formatting", "Specify the output formatting (plain, color or html). The default is plain.", "="); 19 | public static final Argument useDefaultBuildArg = new Argument("--use-default-build", "If set to true and no matching build with given NVR was found, the tool will use the latest (default) build instead. Default value is false.", "="); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/web/ComapreContextExecutingHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.web; 25 | 26 | import java.io.File; 27 | import java.io.IOException; 28 | import java.io.UnsupportedEncodingException; 29 | 30 | import io.jenkins.plugins.report.jtreg.main.comparator.HelpMessage; 31 | 32 | public class ComapreContextExecutingHandler extends ContextExecutingHandler { 33 | 34 | public ComapreContextExecutingHandler(File targetProgram) throws IOException { 35 | super(targetProgram); 36 | } 37 | 38 | @Override 39 | protected String loadDifTemplate() throws IOException { 40 | return loadTemplate("/io/jenkins/plugins/report/jtreg/main/web/comp.html"); 41 | } 42 | 43 | @Override 44 | protected String pritnHelp() throws UnsupportedEncodingException { 45 | return sanitizeHtml(HelpMessage.HELP_MESSAGE) + "\n" + "note:\n" 46 | + "--path path_to_the_jenkins_jobs_directory is already preset, no need to set it\n" 47 | + "examples:\n" 48 | + "--compare --query \"tck jp19 ojdkLatest~rpms * * release sdk * aarch64 beaker x11 defaultgc ignorecp lnxagent *\" --history 5 --nvr \"java-latest-openjdk-19.0.2.0.7-1.rolling" 49 | + ".el8\"\n" 50 | + "--compare --query \"tck jp19 ojdkLatest~rpms * * release sdk * aarch64 beaker x11 defaultgc ignorecp lnxagent *\" --history 1\n" 51 | + "When launched from here, web, the `\" or * or { or } you have to use \\\" and \\* and \\{ and \\}` is NOT CORRECT\n" 52 | + "html wrapper not yet finished, you ust check SOURCE (ctrl+u) for anyviable thing\n"; 53 | } 54 | 55 | private String sanitizeHtml(String helpMessage) { 56 | return helpMessage 57 | .replace("&", "&") 58 | .replace("\"", """) 59 | .replace("'", "'") 60 | .replace("<", "<") 61 | .replace(">", ">"); 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/ReportChartColumn.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | import hudson.Extension; 27 | import hudson.model.Job; 28 | import hudson.model.Project; 29 | import io.jenkins.plugins.report.jtreg.model.BuildReport; 30 | import hudson.views.ListViewColumn; 31 | import hudson.views.ListViewColumnDescriptor; 32 | import java.util.Arrays; 33 | import java.util.List; 34 | import java.util.UUID; 35 | 36 | import org.kohsuke.stapler.DataBoundConstructor; 37 | 38 | public class ReportChartColumn extends ListViewColumn { 39 | 40 | @DataBoundConstructor 41 | public ReportChartColumn() { 42 | } 43 | 44 | public List getJckReport(Job job) { 45 | AbstractReportPublisher settings = ReportAction.getAbstractReportPublisher(((Project) job).getPublishersList()); 46 | List r = new BuildSummaryParser(Arrays.asList("jck", "jtreg"), settings).parseJobReports(job); 47 | try { 48 | ReportProjectAction.cacheSumms(job.getRootDir(), r); 49 | } catch (Exception ex) { 50 | ex.printStackTrace(); 51 | } 52 | return r; 53 | } 54 | 55 | public int getLatestResultFailures(final List reports) { 56 | if (reports == null || reports.isEmpty()) { 57 | return 0; 58 | } else { 59 | BuildReport lastReport = reports.get(reports.size() - 1); 60 | return lastReport.getFailed() + lastReport.getError(); 61 | } 62 | } 63 | 64 | public String generateChartName() { 65 | return "chart"+ UUID.randomUUID().toString().replace("-",""); 66 | } 67 | 68 | @Extension 69 | public static final ReportChartColumnDescriptor DESCRIPTOR = new ReportChartColumnDescriptor(); 70 | 71 | public static class ReportChartColumnDescriptor extends ListViewColumnDescriptor { 72 | 73 | @Override 74 | public boolean shownByDefault() { 75 | return false; 76 | } 77 | 78 | @Override 79 | public String getDisplayName() { 80 | return "JCK and/or JTreg Results"; 81 | } 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/BuildReport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import io.jenkins.plugins.chartjs.Chartjs; 27 | import java.util.List; 28 | 29 | public class BuildReport implements java.io.Serializable { 30 | 31 | private final int buildNumber; 32 | private final String buildName; 33 | private final String buildNameShortened; 34 | private final int passed; 35 | private final int failed; 36 | private final int error; 37 | private final int total; 38 | private final int notRun; 39 | private final int run; 40 | private final List suites; 41 | 42 | public BuildReport(int buildNumber, String buildName, int passed, int failed, int error, List suites, int total, int notRun) { 43 | this.buildNumber = buildNumber; 44 | this.buildName = buildName; 45 | this.passed = passed; 46 | this.failed = failed; 47 | this.error = error; 48 | this.suites = suites; 49 | this.total = total; 50 | this.notRun = notRun; 51 | this.run = 0; 52 | this.buildNameShortened=Chartjs.getShortName(buildName, buildNumber); 53 | } 54 | 55 | public String getBuildNameShortened() { 56 | return buildNameShortened; 57 | } 58 | 59 | 60 | public int getBuildNumber() { 61 | return buildNumber; 62 | } 63 | 64 | public String getBuildName() { 65 | return buildName; 66 | } 67 | 68 | public int getPassed() { 69 | return passed; 70 | } 71 | 72 | public int getFailed() { 73 | return failed; 74 | } 75 | 76 | public int getError() { 77 | return error; 78 | } 79 | 80 | public List getSuites() { 81 | return suites; 82 | } 83 | 84 | public int getTotal() { 85 | return total; 86 | } 87 | 88 | public int getNotRun() { 89 | return notRun; 90 | } 91 | 92 | public int getRun() { 93 | return total - notRun; 94 | } 95 | 96 | public boolean isInvalid() { 97 | return passed == 0 && failed == 0 && error == 0 && total == 0 && notRun == 0 && run == 0; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/SuitesWithResults.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | import java.util.Collections; 30 | 31 | public class SuitesWithResults implements java.io.Serializable { 32 | 33 | public static SuitesWithResults create(List currentBuildTestsList, BuildReport problems, String job, int id) { 34 | List futureSuitests = new ArrayList<>(currentBuildTestsList.size()); 35 | for (SuiteTests suiteTest : currentBuildTestsList) { 36 | final List testsForThisSuite = new ArrayList<>(suiteTest.getTests().size()); 37 | for (String test : suiteTest.getTests()) { 38 | if (isProblem(suiteTest.getName(), test, problems.getSuites())) { 39 | testsForThisSuite.add(new SuiteTestsWithResults.StringWithResult(test, SuiteTestsWithResults.TestStatusSimplified.FAILED_OR_ERROR)); 40 | } else { 41 | testsForThisSuite.add(new SuiteTestsWithResults.StringWithResult(test, SuiteTestsWithResults.TestStatusSimplified.PASSED_OR_MISSING)); 42 | } 43 | } 44 | futureSuitests.add(new SuiteTestsWithResults(suiteTest.getName(), testsForThisSuite, job, id)); 45 | } 46 | return new SuitesWithResults(futureSuitests); 47 | } 48 | 49 | private static boolean isProblem(String suiteName, String test, List probelms) { 50 | for (Suite probelm : probelms) { 51 | if (probelm.getName().equals(suiteName)) { 52 | for (Test t : probelm.getReport().getTestProblems()) { 53 | if (t.getName().equals(test)) { 54 | return true; 55 | } 56 | } 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | private final List suitests; 63 | 64 | public SuitesWithResults(List suitests) { 65 | this.suitests = suitests; 66 | } 67 | 68 | public List getAllTestsAndSuites() { 69 | return Collections.unmodifiableList(suitests); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/Service.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main; 25 | 26 | import com.sun.net.httpserver.HttpServer; 27 | 28 | import io.jenkins.plugins.report.jtreg.main.diff.web.ComapreContextExecutingHandler; 29 | import io.jenkins.plugins.report.jtreg.main.diff.web.DiffContextExecutingHandler; 30 | 31 | import java.io.File; 32 | import java.io.IOException; 33 | import java.net.InetSocketAddress; 34 | 35 | public class Service { 36 | 37 | public static void main(String... args) throws IOException { 38 | String file1 = "/home/tester/vm-shared/TckScripts/jenkins/custom_run_wrappers/diff_jobs_hydra.sh"; 39 | String file2 = "/home/tester/vm-shared/TckScripts/jenkins/custom_run_wrappers/compare_jobs_hydra.sh"; 40 | int port = 9090; 41 | if (args.length == 0) { 42 | souter("Warning! Running with defaults. Not recommended."); 43 | help(); 44 | } else if (args.length == 1) { 45 | port = Integer.parseInt(args[0]); 46 | } else if (args.length == 2) { 47 | file1 = args[0]; 48 | file2 = args[1]; 49 | } else if (args.length == 3) { 50 | file1 = args[0]; 51 | file2 = args[1]; 52 | port = Integer.parseInt(args[2]); 53 | } else { 54 | help(); 55 | throw new RuntimeException("0,1,2 or 3 args expected. Is " + args.length); 56 | } 57 | String b1 = "/diff.html"; 58 | String b2 = "/comp.html"; 59 | HttpServer hs = HttpServer.create(new InetSocketAddress(port), 0); 60 | hs.createContext(b1, new DiffContextExecutingHandler( 61 | new File(file1))); 62 | hs.createContext(b2, new ComapreContextExecutingHandler( 63 | new File(file2))); 64 | hs.start(); 65 | souter(b1 + " server started. Running at " + port + ". Terminate to end. Run for: " + file1); 66 | souter(b2 + " server started. Running at " + port + ". Terminate to end. Run for: " + file2); 67 | 68 | } 69 | 70 | public static void help() { 71 | souter("no argument, defaults"); 72 | souter("one argument, changes port of service"); 73 | souter("two argument, set scriptable backends"); 74 | souter("three argument,first two sets scriptable backends, third is port"); 75 | souter("more, error"); 76 | } 77 | 78 | public static void souter(String s) { 79 | System.out.println(s); 80 | System.err.println(s); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/Report.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import java.util.List; 27 | import java.util.Objects; 28 | 29 | public class Report implements java.io.Serializable { 30 | 31 | private final int testsPassed; 32 | private final int testsNotRun; 33 | private final int testsFailed; 34 | private final int testsError; 35 | private final int testsTotal; 36 | private final List testProblems; 37 | 38 | public Report(int testsPassed, int testsNotRun, int testsFailed, int testsError, int testsTotal, List testProblems) { 39 | this.testsPassed = testsPassed; 40 | this.testsNotRun = testsNotRun; 41 | this.testsFailed = testsFailed; 42 | this.testsError = testsError; 43 | this.testsTotal = testsTotal; 44 | this.testProblems = testProblems; 45 | } 46 | 47 | public int getTestsPassed() { 48 | return testsPassed; 49 | } 50 | 51 | public int getTestsNotRun() { 52 | return testsNotRun; 53 | } 54 | 55 | public int getTestsFailed() { 56 | return testsFailed; 57 | } 58 | 59 | public int getTestsError() { 60 | return testsError; 61 | } 62 | 63 | public int getTestsTotal() { 64 | return testsTotal; 65 | } 66 | 67 | public List getTestProblems() { 68 | return testProblems; 69 | } 70 | 71 | @Override 72 | public boolean equals(Object o) { 73 | if (this == o) { 74 | return true; 75 | } 76 | if (o == null || getClass() != o.getClass()) { 77 | return false; 78 | } 79 | Report report = (Report) o; 80 | return testsPassed == report.testsPassed && testsNotRun == report.testsNotRun && testsFailed == report 81 | .testsFailed && testsError == report.testsError && testsTotal == report.testsTotal && Objects.equals 82 | (testProblems, report.testProblems); 83 | } 84 | 85 | @Override 86 | public int hashCode() { 87 | return Objects.hash(testsPassed, testsNotRun, testsFailed, testsError, testsTotal, testProblems); 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return "Report{" + "testsPassed=" + testsPassed + ", testsNotRun=" + testsNotRun + ", testsFailed=" + 93 | testsFailed + ", testsError=" + testsError + ", testsTotal=" + testsTotal + ", testProblems=" + 94 | testProblems + '}'; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/ReportParserCallable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 27 | import hudson.FilePath; 28 | import io.jenkins.plugins.report.jtreg.model.Report; 29 | import io.jenkins.plugins.report.jtreg.model.Suite; 30 | import io.jenkins.plugins.report.jtreg.parsers.ReportParser; 31 | import hudson.remoting.VirtualChannel; 32 | import jenkins.MasterToSlaveFileCallable; 33 | import org.jenkinsci.remoting.RoleChecker; 34 | 35 | import java.io.File; 36 | import java.io.IOException; 37 | import java.nio.file.FileSystems; 38 | import java.nio.file.Files; 39 | import java.nio.file.Path; 40 | import java.nio.file.PathMatcher; 41 | import java.util.List; 42 | import java.util.stream.Collectors; 43 | import java.util.stream.Stream; 44 | 45 | public class ReportParserCallable extends MasterToSlaveFileCallable> implements FilePath.FileCallable> { 46 | 47 | public static final Suite FAKE_SUITE = new Suite("Fake suite", new Report(0, 0, 0, 0, 0, null)); 48 | 49 | private final String reportMatcherGlob; 50 | private final ReportParser reportParser; 51 | 52 | public ReportParserCallable(String reportMatcherGlob, ReportParser reportParser) { 53 | this.reportParser = reportParser; 54 | if (reportMatcherGlob == null || reportMatcherGlob.isEmpty()) { 55 | this.reportMatcherGlob = "glob:*.{xml,xml.gz}"; 56 | } else { 57 | if (!reportMatcherGlob.startsWith("glob:")) { 58 | reportMatcherGlob = "glob:" + reportMatcherGlob; 59 | } 60 | this.reportMatcherGlob = reportMatcherGlob; 61 | } 62 | } 63 | 64 | @Override 65 | @SuppressFBWarnings(value = {"NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"}, justification = " npe of spotbugs sucks") 66 | public List invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { 67 | PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(reportMatcherGlob); 68 | try (Stream filesStream = Files.walk(f.toPath()).sequential()) { 69 | List result = filesStream 70 | .filter(p -> pathMatcher.matches(p.getFileName())) 71 | .map(reportParser::parsePath) 72 | .filter(e -> e != null) 73 | .sorted() 74 | .collect(Collectors.toList()); 75 | if (result != null && result.size() == 0) { 76 | result.add(getFakeSuite()); 77 | } 78 | return result; 79 | } 80 | } 81 | 82 | private Suite getFakeSuite() { 83 | return FAKE_SUITE; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/formatters/PlainFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.formatters; 25 | 26 | import java.io.PrintStream; 27 | import java.util.Arrays; 28 | 29 | public class PlainFormatter extends BasicFormatter { 30 | 31 | public PlainFormatter(PrintStream stream) { 32 | super(stream); 33 | } 34 | 35 | @Override 36 | public void startBold() { 37 | //no op 38 | } 39 | 40 | @Override 41 | public void startColor(SupportedColors color) { 42 | //no op 43 | } 44 | 45 | @Override 46 | public void reset() { 47 | //no op 48 | } 49 | 50 | @Override 51 | public void initDoc() { 52 | //no op 53 | } 54 | 55 | @Override 56 | public void closeDoc() { 57 | //no op 58 | } 59 | 60 | @Override 61 | public void startTitle2() { 62 | //no op 63 | } 64 | 65 | @Override 66 | public void startTitle1() { 67 | //no op 68 | } 69 | 70 | @Override 71 | public void startTitle3() { 72 | //no op 73 | } 74 | 75 | @Override 76 | public void startTitle4() { 77 | //no op 78 | } 79 | 80 | @Override 81 | public void printTable(String[][] table, int rowSize, int columnSize) { 82 | // first print the first row definitions 83 | for (int i = 1; i < table[0].length; i++) { 84 | super.println(i + ") " + table[0][i]); 85 | table[0][i] = Integer.toString(i); // replace the item with its definition (number) 86 | } 87 | 88 | // get the length of the longest item in each column 89 | int[] lengths = new int[table[0].length]; 90 | Arrays.fill(lengths, 0); 91 | for (int i = 0; i < rowSize; i++) { 92 | for (int j = 0; j < columnSize; j++) { 93 | if (table[i][j] != null && table[i][j].length() > lengths[j]) { 94 | lengths[j] = table[i][j].length(); 95 | } 96 | } 97 | } 98 | 99 | // print the table 100 | for (int i = 0; i < rowSize; i++) { 101 | for (int j = 0; j < columnSize; j++) { 102 | int len = 0; 103 | if (table[i][j] != null) { 104 | super.print(table[i][j] + " "); 105 | len = table[i][j].length(); 106 | } else { 107 | super.print(" "); 108 | } 109 | // printing spaces to make the table look better 110 | for (int k = len; k < lengths[j]; k++) { 111 | super.print(" "); 112 | } 113 | super.print("| "); 114 | } 115 | super.print("\n"); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/ReportAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | import hudson.model.AbstractBuild; 27 | import hudson.model.Action; 28 | import hudson.model.Descriptor; 29 | import hudson.model.Job; 30 | import hudson.tasks.Publisher; 31 | import hudson.util.DescribableList; 32 | import java.util.Collection; 33 | import java.util.Collections; 34 | import java.util.HashSet; 35 | import java.util.Set; 36 | import java.util.stream.Collectors; 37 | import jenkins.tasks.SimpleBuildStep; 38 | import org.kohsuke.stapler.StaplerProxy; 39 | 40 | public class ReportAction implements Action, StaplerProxy, SimpleBuildStep.LastBuildAction { 41 | 42 | private final AbstractBuild build; 43 | private final Set prefixes = new HashSet<>(); 44 | 45 | public ReportAction(AbstractBuild build) { 46 | if (build == null) { 47 | throw new IllegalArgumentException("Build cannot be null"); 48 | } 49 | this.build = build; 50 | } 51 | 52 | public void addPrefix(String prefix) { 53 | if (prefix == null || prefix.trim().isEmpty()) { 54 | throw new IllegalArgumentException("Prefix cannot be empty"); 55 | } 56 | prefixes.add(prefix); 57 | } 58 | 59 | @Override 60 | public String getIconFileName() { 61 | return "graph.png"; 62 | } 63 | 64 | @Override 65 | public String getDisplayName() { 66 | return prefixes.stream() 67 | .sequential() 68 | .map(s -> s.toUpperCase()) 69 | .collect(Collectors.joining(", ", "", " Reports")); 70 | } 71 | 72 | @Override 73 | public String getUrlName() { 74 | return "java-reports"; 75 | } 76 | 77 | @Override 78 | public BuildReportExtended getTarget() { 79 | try { 80 | AbstractReportPublisher settings = getAbstractReportPublisher(build.getProject().getPublishersList()); 81 | BuildReportExtended report = new BuildSummaryParser(prefixes, settings).parseBuildReportExtended(build); 82 | return report; 83 | } catch (Exception ex) { 84 | ex.printStackTrace(); 85 | } 86 | return null; 87 | } 88 | 89 | @Override 90 | public Collection getProjectActions() { 91 | Job job = build.getParent(); 92 | return Collections.singleton(new ReportProjectAction(job, prefixes)); 93 | } 94 | 95 | public static AbstractReportPublisher getAbstractReportPublisher(DescribableList> publishersList) { 96 | for (Publisher publisher : publishersList) { 97 | if (publisher instanceof AbstractReportPublisher){ 98 | return (AbstractReportPublisher)publisher; 99 | } 100 | } 101 | return null; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/Options.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.comparator.jobs.JobsProvider; 4 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.Formatter; 5 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.PlainFormatter; 6 | 7 | public class Options { 8 | private Operations operation; 9 | private String jobsPath; 10 | private String nvrQuery; 11 | private int numberOfBuilds; 12 | private boolean skipFailed; 13 | private boolean forceVague; 14 | private boolean onlyVolatile; 15 | private String exactTestsRegex; 16 | private Formatter formatter; 17 | private boolean useDefaultBuild; 18 | private JobsProvider jobsProvider; 19 | private boolean printVirtual; 20 | private boolean die; 21 | 22 | public Options() { 23 | this.nvrQuery = ""; 24 | this.numberOfBuilds = 1; 25 | this.skipFailed = true; 26 | this.forceVague = false; 27 | this.onlyVolatile = false; 28 | this.exactTestsRegex = ".*"; 29 | this.formatter = new PlainFormatter(System.out); 30 | this.useDefaultBuild = false; 31 | this.jobsProvider = null; 32 | this.printVirtual = false; 33 | this.die = false; 34 | } 35 | 36 | public void setDie(boolean die) { 37 | this.die = die; 38 | } 39 | 40 | public boolean isDie() { 41 | return die; 42 | } 43 | 44 | public Operations getOperation() { 45 | return operation; 46 | } 47 | 48 | public void setOperation(Operations operation) { 49 | this.operation = operation; 50 | } 51 | 52 | public String getJobsPath() { 53 | return jobsPath; 54 | } 55 | 56 | public void setJobsPath(String jobsPath) { 57 | this.jobsPath = jobsPath; 58 | } 59 | 60 | public String getNvrQuery() { 61 | return nvrQuery; 62 | } 63 | 64 | public void setNvrQuery(String nvr) { 65 | this.nvrQuery = nvr; 66 | } 67 | 68 | public int getNumberOfBuilds() { 69 | return numberOfBuilds; 70 | } 71 | 72 | public void setNumberOfBuilds(int numberOfBuilds) { 73 | this.numberOfBuilds = numberOfBuilds; 74 | } 75 | 76 | public boolean isSkipFailed() { 77 | return skipFailed; 78 | } 79 | 80 | public void setSkipFailed(boolean skipFailed) { 81 | this.skipFailed = skipFailed; 82 | } 83 | 84 | public boolean isForceVague() { 85 | return forceVague; 86 | } 87 | 88 | public void setForceVague(boolean forceVagueQuery) { 89 | this.forceVague = forceVagueQuery; 90 | } 91 | 92 | public boolean isOnlyVolatile() { 93 | return onlyVolatile; 94 | } 95 | 96 | public void setOnlyVolatile(boolean onlyVolatile) { 97 | this.onlyVolatile = onlyVolatile; 98 | } 99 | 100 | public String getExactTestsRegex() { 101 | return exactTestsRegex; 102 | } 103 | 104 | public void setExactTestsRegex(String exactTestsRegex) { 105 | this.exactTestsRegex = exactTestsRegex; 106 | } 107 | 108 | public Formatter getFormatter() { 109 | return formatter; 110 | } 111 | 112 | public void setFormatter(Formatter formatter) { 113 | this.formatter = formatter; 114 | } 115 | 116 | public JobsProvider getJobsProvider() { 117 | return jobsProvider; 118 | } 119 | 120 | public void setJobsProvider(JobsProvider jobsProvider) { 121 | this.jobsProvider = jobsProvider; 122 | } 123 | 124 | public boolean isUseDefaultBuild() { 125 | return useDefaultBuild; 126 | } 127 | 128 | public void setUseDefaultBuild(boolean useDefaultBuild) { 129 | this.useDefaultBuild = useDefaultBuild; 130 | } 131 | 132 | public boolean isPrintVirtual() { 133 | return printVirtual; 134 | } 135 | 136 | public void setPrintVirtual(boolean printVirtual) { 137 | this.printVirtual = printVirtual; 138 | } 139 | 140 | // enum of all available operations 141 | public enum Operations { 142 | List, Enumerate, Compare, Print 143 | } 144 | } -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/HelpMessage.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.comparator.arguments.ArgumentsDeclaration; 4 | import io.jenkins.plugins.report.jtreg.main.comparator.jobs.JobsByQuery; 5 | import io.jenkins.plugins.report.jtreg.main.comparator.jobs.JobsByRegex; 6 | 7 | final public class HelpMessage { 8 | public static final String HELP_MESSAGE = 9 | //80-characters-long-comment------------------------------------------------------ 10 | "Test Variant Comparator Usage: java -cp [arguments...]\n" + 11 | "\n" + 12 | "Where mainclass is:\n" + 13 | " io.jenkins.plugins.report.jtreg.main.comparator.VariantComparator\n" + 14 | "\n" + 15 | "And arguments include:\n" + 16 | "\n" + 17 | " " + ArgumentsDeclaration.pathArg.getName() + ArgumentsDeclaration.pathArg.getUsage() + "\n" + 18 | " " + ArgumentsDeclaration.pathArg.getHelp() + "\n" + 19 | "\n" + 20 | " You can choose one of these to filter the jobs by their name:\n" + 21 | " " + JobsByQuery.queryArg.getName() + JobsByQuery.queryArg.getUsage() + "\n" + 22 | " " + JobsByQuery.queryArg.getHelp() + "\n" + 23 | " " + JobsByQuery.exactLengthArg.getName() + JobsByQuery.exactLengthArg.getUsage() + "\n" + 24 | " " + JobsByQuery.exactLengthArg.getHelp() + "\n" + 25 | " " + JobsByRegex.regexArg.getName() + JobsByRegex.regexArg.getUsage() + "\n" + 26 | " " + JobsByRegex.regexArg.getHelp() + "\n" + 27 | "\n" + 28 | " You need to choose ONE operation from these:\n" + 29 | " " + ArgumentsDeclaration.printArg.getName() + "\n" + 30 | " " + ArgumentsDeclaration.printArg.getHelp() + "\n" + 31 | " " + ArgumentsDeclaration.enumerateArg.getName() + "\n" + 32 | " " + ArgumentsDeclaration.enumerateArg.getHelp() + "\n" + 33 | " " + ArgumentsDeclaration.listArg.getName() + "\n" + 34 | " " + ArgumentsDeclaration.listArg.getHelp() + "\n" + 35 | " " + ArgumentsDeclaration.compareArg.getName() + "\n" + 36 | " " + ArgumentsDeclaration.compareArg.getHelp() + "\n" + 37 | " " + ArgumentsDeclaration.virtualArg.getName() + "\n" + 38 | " " + ArgumentsDeclaration.virtualArg.getHelp() + "\n" + 39 | "\n" + 40 | " Other arguments:\n" + 41 | " " + ArgumentsDeclaration.helpArg.getName() + "\n" + 42 | " " + ArgumentsDeclaration.helpArg.getHelp() + "\n" + 43 | " " + ArgumentsDeclaration.skipFailedArg.getName() + ArgumentsDeclaration.skipFailedArg.getUsage() + "\n" + 44 | " " + ArgumentsDeclaration.skipFailedArg.getHelp() + "\n" + 45 | " " + ArgumentsDeclaration.nvrArg.getName() + ArgumentsDeclaration.nvrArg.getUsage() + "\n" + 46 | " " + ArgumentsDeclaration.nvrArg.getHelp() + "\n" + 47 | " " + ArgumentsDeclaration.historyArg.getName() + ArgumentsDeclaration.historyArg.getUsage() + "\n" + 48 | " " + ArgumentsDeclaration.historyArg.getHelp() + "\n" + 49 | " " + ArgumentsDeclaration.onlyVolatileArg.getName() + ArgumentsDeclaration.onlyVolatileArg.getUsage() + "\n" + 50 | " " + ArgumentsDeclaration.onlyVolatileArg.getHelp() + "\n" + 51 | " " + ArgumentsDeclaration.forceArg.getName() + "\n" + 52 | " " + ArgumentsDeclaration.forceArg.getHelp() + "\n" + 53 | " " + ArgumentsDeclaration.formattingArg.getName() + ArgumentsDeclaration.formattingArg.getUsage() + "\n" + 54 | " " + ArgumentsDeclaration.formattingArg.getHelp() + "\n" + 55 | "\n" + 56 | "Query string syntax:\n" + 57 | JobsByQuery.queryStringUsage + 58 | "\n" + 59 | "NVR query syntax:\n" + 60 | " The syntax of the NVR query is simple: it either takes an asterisk (*)\n" + 61 | " all NVRs, or it takes a RegEx of a single NVR it should match, or\n" + 62 | " multiple RegExes in a set ({}) with same rules as the query string set.\n"; 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/report/jtreg/main/comparator/PrintTableTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.ColorFormatter; 4 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.Formatter; 5 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.HtmlFormatter; 6 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.PlainFormatter; 7 | import org.junit.jupiter.api.*; 8 | 9 | 10 | import java.io.ByteArrayOutputStream; 11 | import java.io.PrintStream; 12 | 13 | public class PrintTableTest { 14 | private static String[][] table; 15 | 16 | @BeforeEach 17 | public void updateTable() { 18 | table = new String[][] { 19 | {null, "first item", "second item", "third item"}, 20 | {"second row", "X", "this is a very long text in a center cell of a table", "X"}, 21 | {"third row", null, "", "X"}, 22 | {"fourth row", "X", "X", "X", "this is out of range and it won't be shown"} 23 | }; 24 | } 25 | 26 | @Test 27 | public void testPlainTablePrinting() { 28 | ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 29 | PrintStream printStream = new PrintStream(outStream); 30 | Formatter f = new PlainFormatter(printStream); 31 | 32 | String[][] newTable = table; 33 | 34 | f.printTable(newTable, 4, 4); 35 | 36 | Assertions.assertEquals("1) first item\n" + 37 | "2) second item\n" + 38 | "3) third item\n" + 39 | " | 1 | 2 | 3 | \n" + 40 | "second row | X | this is a very long text in a center cell of a table | X | \n" + 41 | "third row | | | X | \n" + 42 | "fourth row | X | X | X | \n", outStream.toString()); 43 | } 44 | 45 | @Test 46 | public void testColorTablePrinting() { 47 | ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 48 | PrintStream printStream = new PrintStream(outStream); 49 | Formatter f = new ColorFormatter(printStream); 50 | 51 | f.printTable(table, 4, 4); 52 | 53 | Assertions.assertEquals("\u001B[1m1) \u001B[0mfirst item\n" + 54 | "\u001B[1m2) \u001B[0msecond item\n" + 55 | "\u001B[1m3) \u001B[0mthird item\n" + 56 | " | \u001B[1m1\u001B[0m | \u001B[1m2\u001B[0m | \u001B[1m3\u001B[0m | \n" + 57 | "second row | \u001B[31mX\u001B[0m | this is a very long text in a center cell of a table | \u001B[31mX\u001B[0m | \n" + 58 | "third row | | | \u001B[31mX\u001B[0m | \n" + 59 | "fourth row | \u001B[31mX\u001B[0m | \u001B[31mX\u001B[0m | \u001B[31mX\u001B[0m | \n", outStream.toString()); 60 | } 61 | 62 | @Test 63 | public void testHtmlTablePrinting() { 64 | ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 65 | PrintStream printStream = new PrintStream(outStream); 66 | Formatter f = new HtmlFormatter(printStream); 67 | 68 | f.printTable(table, 4, 4); 69 | 70 | Assertions.assertEquals("\n" + 71 | "
      \n" + 72 | "
    • 1: first item
    • \n" + 73 | "
    • 2: second item
    • \n" + 74 | "
    • 3: third item
    • \n" + 75 | "
    \n" + 76 | "\n" + 77 | "\n" + 78 | "\n" + 79 | "\n" + 80 | "\n" + 81 | "\n" + 82 | "\n" + 83 | "\n" + 84 | "\n" + 85 | "\n" + 86 | "\n" + 87 | "\n" + 88 | "\n" + 89 | "\n" + 90 | "\n" + 91 | "\n" + 92 | "\n" + 93 | "\n" + 94 | "\n" + 95 | "\n" + 96 | "\n" + 97 | "\n" + 98 | "\n" + 99 | "\n" + 100 | "\n" + 101 | "
    123
    second rowXthis is a very long text in a center cell of a tableX
    third rowX
    fourth rowXXX
    \n", outStream.toString()); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/report/jtreg/ReportChartColumn/chartLogicColumn.js: -------------------------------------------------------------------------------- 1 | // (s.trim())); 25 | } 26 | var data_failed_element = document.getElementById('jckChart-failed-'+id) 27 | if (data_failed_element == null){ 28 | continue; 29 | } else { 30 | var data_failed = data_failed_element.textContent.split(/\s*,\s*/).flatMap((s) =>(s.trim())); 31 | } 32 | var data_error_element = document.getElementById('jckChart-error-'+id) 33 | if (data_error_element == null){ 34 | continue; 35 | } else { 36 | var data_error = data_error_element.textContent.split(/\s*,\s*/).flatMap((s) =>(s.trim())); 37 | } 38 | var data_url_element = document.getElementById('jckChart-url-'+id) 39 | if (data_url_element == null){ 40 | continue; 41 | } else { 42 | var data_url = data_url_element.textContent.trim(); 43 | } 44 | 45 | if (typeof jckChartNameVar == 'undefined') { 46 | var jckChartNameVar = {}; 47 | } 48 | var dataJckView = { 49 | type: 'line', 50 | url_from_job: data_url, 51 | data: { 52 | labels: data_builds, 53 | datasets: [ 54 | { 55 | label: "Error", 56 | fill: true, 57 | backgroundColor: "rgba(255,0,255,0.2)", 58 | borderColor: "rgba(255,0,255,1)", 59 | pointBackgroundColor: "rgba(255,0,255,1)", 60 | pointBorderColor: "#fff", 61 | pointHoverBackgroundColor: "#fff", 62 | pointHoverBorderColor: "rgba(255,0,255,1)", 63 | pointRadius: 4, 64 | data: data_error 65 | }, 66 | { 67 | label: "Failed", 68 | fill: true, 69 | backgroundColor: "rgba(255,0,0,0.2)", 70 | borderColor: "rgba(255,0,0,1)", 71 | pointBackgroundColor: "rgba(255,0,0,1)", 72 | pointBorderColor: "#fff", 73 | pointHoverBackgroundColor: "#fff", 74 | pointHoverBorderColor: "rgba(255,0,0,1)", 75 | pointRadius: 4, 76 | data: data_failed 77 | } 78 | ] 79 | }, 80 | options: { 81 | plugins: { 82 | legend: { display: false } 83 | }, 84 | interaction: { 85 | mode: 'index', 86 | intersect: false 87 | }, 88 | onClick: (e) => { 89 | var chart = e.chart; 90 | var activePoints = chart.getElementsAtEventForMode(e, 'index', { intersect: false }, true); 91 | var point = activePoints[0] 92 | var datasetIndex = point.datasetIndex //labels are for all data together, no need to look into exact dataset 93 | var index = point.index 94 | var result = chart.config.data.labels[index] 95 | var buildId = result.substring(result.lastIndexOf(":") + 1) //thsi works even without :; fixme, add NVR? 96 | window.open("/"+chart.config._config.url_from_job+buildId+"/java-reports", "_blank"); 97 | } 98 | } 99 | }; 100 | var ctx = document.getElementById("jckChart-"+id).getContext("2d"); 101 | jckChartNameVar[id] = new Chart(ctx, dataJckView); 102 | 103 | } 104 | } 105 | window.addEventListener('load', readJcks, false); 106 | // ]]> 107 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | org.jenkins-ci.plugins 7 | plugin 8 | 4.65 9 | 10 | io.jenkins.plugins 11 | report-jtreg 12 | 2.0-SNAPSHOT 13 | 14 | ${packaging-type} 15 | JTReg Plugin 16 | 17 | 18 | 4.2.1.5 19 | 2.400 20 | 21 | 22 | 23 | 24 | baiduzhyi.devel 25 | Stanislav Baiduzhyi 26 | baiduzhyi.devel@gmail.com 27 | 28 | 29 | jvanek 30 | Jiri Vanek 31 | jvanek@redhat.com 32 | 33 | 34 | 35 | 36 | 37 | MIT 38 | https://www.opensource.org/licenses/mit-license.php 39 | 40 | 41 | 42 | https://github.com/jenkinsci/${project.artifactId}-plugin 43 | 44 | scm:git:https://github.com/jenkinsci/${project.artifactId}-plugin.git 45 | scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git 46 | https://github.com/jenkinsci/${project.artifactId}-plugin 47 | HEAD 48 | 49 | 50 | 51 | 52 | 53 | 54 | jar 55 | 56 | jar 57 | 58 | 59 | 60 | 61 | org.jenkins-ci.main 62 | jenkins-core 63 | ${jenkins.version} 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | maven-assembly-plugin 72 | 3.6.0 73 | 74 | 75 | jar-with-dependencies 76 | 77 | 78 | 79 | 80 | create-services-archive 81 | package 82 | 83 | single 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | hpi 95 | 96 | true 97 | 98 | 99 | hpi 100 | 101 | 102 | 103 | 104 | 105 | 106 | repo.jenkins-ci.org 107 | https://repo.jenkins-ci.org/public/ 108 | 109 | 110 | 111 | 112 | repo.jenkins-ci.org 113 | https://repo.jenkins-ci.org/public/ 114 | 115 | 116 | 117 | 118 | 119 | io.jenkins.plugins 120 | chartjs-api 121 | ${chartjs.version} 122 | 123 | 124 | com.google.code.gson 125 | gson 126 | 2.10.1 127 | 128 | 129 | com.fasterxml.woodstox 130 | woodstox-core 131 | 5.4.0 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/model/SuiteTestsWithResults.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.model; 25 | 26 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 27 | import io.jenkins.plugins.report.jtreg.JenkinsReportJckGlobalConfig; 28 | 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | 32 | import java.util.Collections; 33 | 34 | public class SuiteTestsWithResults implements java.io.Serializable { 35 | 36 | public static String getDiffServer() { 37 | return JenkinsReportJckGlobalConfig.getGlobalDiffUrl() + "/diff.html"; 38 | } 39 | public static String getCompServer() { 40 | return JenkinsReportJckGlobalConfig.getGlobalDiffUrl() + "/comp.html"; 41 | } 42 | 43 | private static String getDiffUrlStub() { 44 | return getDiffServer() + "?generated-part=+-view%3Dall-tests+++-view%3Dinfo-summary+++-view%3Dinfo-summary-suites+++-output%3Dhtml++&custom-part=";//+job+number //eg as above; 45 | } 46 | 47 | private static final int MAX = 1000; 48 | private final String name; 49 | 50 | @SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "should be internal implementation only, and thus ArrayList and that is serialisable") 51 | private final List tests; 52 | private final String job; 53 | private final int id; 54 | 55 | public SuiteTestsWithResults(String name, List tests, String job, int id) { 56 | this.name = name; 57 | this.tests = tests; 58 | this.job = job; 59 | this.id = id; 60 | } 61 | 62 | public String getName() { 63 | return name; 64 | } 65 | 66 | public List getTests() { 67 | return Collections.unmodifiableList(tests); 68 | } 69 | 70 | public List getTestsLimited() { 71 | if (tests.size() <= MAX) { 72 | return getTests(); 73 | } else { 74 | final List truncated = new ArrayList<>(1001); 75 | for (int i = 0; i < MAX; i++) { 76 | StringWithResult get = tests.get(i); 77 | truncated.add(get); 78 | } 79 | return truncated; 80 | } 81 | } 82 | 83 | public String getSentence() { 84 | if (tests == null || tests.isEmpty() ) { 85 | return "... No tests at all. Feel free to use our cmdline diff tool or "; 86 | } else if (tests.size() <= MAX) { 87 | return "... Shown all " + tests.size() + " tests. Feel free to use our cmdline diff tool or "; 88 | } else { 89 | return "... Shown " + MAX + " from " + tests.size() + " tests. To see remaining " + (tests.size() - 1000) + " use our cmdline diff tool or "; 90 | } 91 | } 92 | 93 | public String getLink() { 94 | return getDiffUrlStub() + job + "+" + id; 95 | } 96 | 97 | public static class StringWithResult { 98 | 99 | private final String testName; 100 | private final TestStatusSimplified status; 101 | 102 | public StringWithResult(String testName, TestStatusSimplified status) { 103 | this.testName = testName; 104 | this.status = status; 105 | } 106 | 107 | public TestStatusSimplified getStatus() { 108 | return status; 109 | } 110 | 111 | public String getTestName() { 112 | return testName; 113 | } 114 | 115 | } 116 | 117 | public static enum TestStatusSimplified { 118 | PASSED_OR_MISSING, FAILED_OR_ERROR; 119 | 120 | //jelly dont know enums! 121 | public boolean isFailed() { 122 | return (this == FAILED_OR_ERROR); 123 | } 124 | 125 | public boolean isPassed() { 126 | return (this == PASSED_OR_MISSING); 127 | } 128 | 129 | @Override 130 | public String toString() { 131 | switch (this) { 132 | case PASSED_OR_MISSING: 133 | return "(PASS or MISSING)"; 134 | case FAILED_OR_ERROR: 135 | return "(FAILED or ERROR)"; 136 | } 137 | throw new RuntimeException("Unknown enum member"); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/BuildReportExtended.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg; 25 | 26 | import io.jenkins.plugins.report.jtreg.model.BuildReport; 27 | import io.jenkins.plugins.report.jtreg.model.Suite; 28 | import io.jenkins.plugins.report.jtreg.model.SuiteTestChanges; 29 | import io.jenkins.plugins.report.jtreg.model.SuiteTestsWithResults; 30 | import io.jenkins.plugins.report.jtreg.model.SuitesWithResults; 31 | 32 | import java.util.List; 33 | 34 | public class BuildReportExtended extends BuildReport { 35 | 36 | private final List addedSuites; 37 | private final List removedSuites; 38 | private final List testChanges; 39 | private final int total; 40 | private final int notRun; 41 | private final SuitesWithResults allTests; 42 | private final String job; 43 | 44 | public BuildReportExtended(int buildNumber, String buildName, int passed, int failed, int error, List suites, 45 | List addedSuites, List removedSuites, List testChanges, int total, int notRun, SuitesWithResults allTests, String job) { 46 | super(buildNumber, buildName, passed, failed, error, suites, total, notRun); 47 | this.job = job; 48 | this.addedSuites = addedSuites; 49 | this.removedSuites = removedSuites; 50 | this.testChanges = testChanges; 51 | this.total = total; 52 | this.notRun = notRun; 53 | this.allTests = allTests; 54 | } 55 | 56 | public String getPreviousLink() { 57 | return "../../" + (getBuildNumber() - 1) + "/java-reports"; 58 | } 59 | 60 | public String getPreviousLinkName() { 61 | return " << " + (getBuildNumber() - 1) + " << "; 62 | } 63 | 64 | public String getNextLink() { 65 | return "../../" + (getBuildNumber() + 1) + "/java-reports"; 66 | } 67 | 68 | public String getNextLinkName() { 69 | return " >> " + (getBuildNumber() + 1) + " >> "; 70 | } 71 | 72 | public List getAddedSuites() { 73 | return addedSuites; 74 | } 75 | 76 | public List getRemovedSuites() { 77 | return removedSuites; 78 | } 79 | 80 | public List getTestChanges() { 81 | return testChanges; 82 | } 83 | 84 | public String getJob() { 85 | return job; 86 | } 87 | 88 | @Override 89 | public int getTotal() { 90 | return total; 91 | } 92 | 93 | @Override 94 | public int getNotRun() { 95 | return notRun; 96 | } 97 | 98 | public SuitesWithResults getAllTests() { 99 | return allTests; 100 | } 101 | 102 | private static String getDiffUrlStub(){ 103 | return SuiteTestsWithResults.getDiffServer() + "?generated-part=+-view%3Ddiff-list+++-view%3Ddiff-summary+++-view%3Ddiff-summary-suites+++-view%3Dinfo-problems+++-view%3Dinfo-summary+++-output%3Dhtml++-fill++&custom-part=";//+job+numbers //eg as above; 104 | } 105 | 106 | public String getLinkDiff() { 107 | return getDiffUrlStub() + job + "+" + getBuildNumber() + "+" + lowestBuildForFil(); 108 | } 109 | 110 | private int lowestBuildForFil() { 111 | if (getBuildNumber() > 10) { 112 | return getBuildNumber() - 10; 113 | } else { 114 | return 1; 115 | } 116 | } 117 | 118 | private static String getTracesUrlStub() { 119 | return SuiteTestsWithResults.getDiffServer() + "?generated-part=+-view%3Dinfo+++-output%3Dhtml++&custom-part=";//+job+numbers //eg as above; 120 | } 121 | 122 | private static String getCompUrlStub() { 123 | return SuiteTestsWithResults.getCompServer() + "?generated-part=&custom-part=--compare+";//+job+numbers //eg as above; 124 | } 125 | 126 | public String getLinkTraces() { 127 | return getTracesUrlStub() + job + "+" + getBuildNumber(); 128 | } 129 | 130 | public boolean isDiffTool() { 131 | return JenkinsReportJckGlobalConfig.isGlobalDiffUrl(); 132 | } 133 | 134 | public String getCompareArches() { 135 | return getCompUrlStub() + ("--query+" + job.replaceAll("-\\.", "+") + "+--nvr+" + getBuildName()).replace("#","%23"); 136 | } 137 | 138 | public String getCompareOsses() { 139 | return getCompUrlStub() + ("--query+" + job.replaceAll("-\\.", "+") + "+--nvr+" + getBuildName()).replace("#","%23"); 140 | } 141 | 142 | public String getCompareVariants() { 143 | return getCompUrlStub() + ("--query+" + job.replaceAll("-\\.", "+") + "+--nvr+" + getBuildName()).replace("#","%23"); 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/Builds.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.main.diff.cmdline.JobsRecognition; 4 | 5 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.Formatter; 6 | import org.w3c.dom.Document; 7 | import javax.xml.parsers.DocumentBuilder; 8 | import javax.xml.parsers.DocumentBuilderFactory; 9 | import java.io.File; 10 | import java.util.*; 11 | 12 | public class Builds { 13 | // checks if the given build was successful 14 | private static boolean checkIfCorrect(File build, boolean requireSuccessful) { 15 | if (requireSuccessful) { 16 | try { 17 | File buildXml = new File(build.getAbsolutePath() + "/build.xml"); 18 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 19 | DocumentBuilder builder = factory.newDocumentBuilder(); 20 | Document doc = builder.parse(buildXml); 21 | doc.getDocumentElement().normalize(); 22 | 23 | String result = doc 24 | .getElementsByTagName("result").item(0) 25 | .getChildNodes().item(0) 26 | .getNodeValue(); 27 | 28 | return result.equals("SUCCESS") || result.equals("UNSTABLE"); 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | return false; 33 | } else { 34 | return true; 35 | } 36 | } 37 | 38 | // checks if the build has the same NVR as given 39 | static boolean checkForNvr(File build, String nvrQuery) { 40 | // nvrQuery has the same syntax as query string 41 | if (nvrQuery.equals("") || nvrQuery.equals("*")) { 42 | return true; 43 | } 44 | String buildNvr = JobsRecognition.getChangelogsNvr(build); 45 | if (buildNvr == null) { 46 | return false; 47 | } else if (nvrQuery.charAt(0) == '{') { 48 | if (nvrQuery.charAt(nvrQuery.length() - 1) != '}') { 49 | throw new RuntimeException("Expected closing }."); 50 | } 51 | String[] nvrs = nvrQuery.substring(1, nvrQuery.length() - 1).split(","); 52 | return Arrays.stream(nvrs).anyMatch(s -> buildNvr.matches(s)); 53 | } else { 54 | return buildNvr.matches(nvrQuery); 55 | } 56 | } 57 | 58 | // gets all the compatible builds with the given parameters and returns them in a list 59 | public static ArrayList getBuilds( 60 | File job, boolean skipFailed, String nvrQuery, int numberOfBuilds, boolean useDefaultBuild, Formatter formatter) { 61 | 62 | ArrayList listOfBuilds = new ArrayList<>(); 63 | 64 | File buildDir = new File(job.getAbsolutePath() + "/builds/"); 65 | File[] filesInDir = buildDir.listFiles(); 66 | // no builds => return empty list 67 | if (filesInDir == null) { 68 | return listOfBuilds; 69 | } 70 | File[] buildsInDir = Arrays 71 | .stream(filesInDir) 72 | .filter(File::isDirectory) 73 | .toArray(File[]::new); 74 | 75 | // sorting and then reversing to be sure it goes from the newest build to the oldest 76 | // sorting by parsing the build name to an integer first (to sort correctly) 77 | Arrays.sort(buildsInDir, Comparator.comparingInt(a -> Integer.parseInt(a.getName()))); 78 | Collections.reverse(Arrays.asList(buildsInDir)); 79 | 80 | int buildsChecked = 0; 81 | for (File build : buildsInDir) { 82 | if (checkIfCorrect(build, skipFailed) && checkForNvr(build, nvrQuery) && buildsChecked < numberOfBuilds) { 83 | listOfBuilds.add(build); 84 | } 85 | 86 | // only add to the counter when the build was successful, or when we also take unsuccessful builds 87 | if (!skipFailed || checkIfCorrect(build, true)) { 88 | buildsChecked++; 89 | } 90 | } 91 | 92 | if (!nvrQuery.equals("") && listOfBuilds.size() == 0 && useDefaultBuild) { 93 | for (File build : buildsInDir) { 94 | if (checkIfCorrect(build, skipFailed)) { 95 | listOfBuilds.add(build); 96 | formatter.startColor(Formatter.SupportedColors.Yellow); 97 | formatter.println("Cannot find job " + getJobName(build) + " which matches " + nvrQuery + 98 | ", instead using build " + getBuildNumber(build) + " with nvr " + getNvr(build) + "."); 99 | formatter.reset(); 100 | break; 101 | } 102 | } 103 | } 104 | 105 | return listOfBuilds; 106 | } 107 | 108 | public static String getJobName(File build) { 109 | String path = build.getAbsolutePath(); 110 | String[] split = path.split("/"); 111 | if (split[split.length - 2].equals("builds")) { // second last should be the "builds" directory 112 | return split[split.length - 3]; // third last is the job name 113 | } else { 114 | throw new RuntimeException("The getJobName() function got invalid build path."); 115 | } 116 | } 117 | 118 | public static String getBuildNumber(File build) { 119 | String path = build.getAbsolutePath(); 120 | String[] split = path.split("/"); 121 | if (split[split.length - 2].equals("builds")) { // second last should be the "builds" directory 122 | return split[split.length - 1]; // the last is the build number 123 | } else { 124 | throw new RuntimeException("The getBuildNumber() function got invalid build path."); 125 | } 126 | } 127 | 128 | public static String getNvr(File build) { 129 | return JobsRecognition.getChangelogsNvr(build); 130 | } 131 | } -------------------------------------------------------------------------------- /src/test/resources/io/jenkins/plugins/report/jtreg/main/comparator/dummyNvr1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2387059 4 | java-17-openjdk-portable 5 | 17.0.6.0.10 6 | 6.el7openjdkportable 7 | java-17-openjdk-portable-17.0.6.0.10-6.el7openjdkportable 8 | 2023-02-22 07:51:22.780374 9 | 10 | 11 | java-17-openjdk-portable-devel 12 | 17.0.6.0.10 13 | 6.el7openjdkportable 14 | java-17-openjdk-portable-devel-17.0.6.0.10-6.el7openjdkportable 15 | x86_64 16 | http://download.eng.brq.redhat.com/brewroot/packages/java-17-openjdk-portable/17.0.6.0.10/6.el7openjdkportable/x86_64/java-17-openjdk-portable-devel-17.0.6.0.10-6.el7openjdkportable.x86_64.rpm 17 | 0ceb745e24cf97b54e4da71b1adb0c42 18 | 19 | 20 | java-17-openjdk-portable-misc 21 | 17.0.6.0.10 22 | 6.el7openjdkportable 23 | java-17-openjdk-portable-misc-17.0.6.0.10-6.el7openjdkportable 24 | x86_64 25 | http://download.eng.brq.redhat.com/brewroot/packages/java-17-openjdk-portable/17.0.6.0.10/6.el7openjdkportable/x86_64/java-17-openjdk-portable-misc-17.0.6.0.10-6.el7openjdkportable.x86_64.rpm 26 | d4934a8e796bc8370bafe797ddc3fa84 27 | 28 | 29 | java-17-openjdk-portable-unstripped 30 | 17.0.6.0.10 31 | 6.el7openjdkportable 32 | java-17-openjdk-portable-unstripped-17.0.6.0.10-6.el7openjdkportable 33 | x86_64 34 | http://download.eng.brq.redhat.com/brewroot/packages/java-17-openjdk-portable/17.0.6.0.10/6.el7openjdkportable/x86_64/java-17-openjdk-portable-unstripped-17.0.6.0.10-6.el7openjdkportable.x86_64.rpm 35 | 55077a3a7adf7c02e824b4cde7ae31ec 36 | 37 | 38 | java-17-openjdk-portable-docs 39 | 17.0.6.0.10 40 | 6.el7openjdkportable 41 | java-17-openjdk-portable-docs-17.0.6.0.10-6.el7openjdkportable 42 | x86_64 43 | http://download.eng.brq.redhat.com/brewroot/packages/java-17-openjdk-portable/17.0.6.0.10/6.el7openjdkportable/x86_64/java-17-openjdk-portable-docs-17.0.6.0.10-6.el7openjdkportable.x86_64.rpm 44 | bb4870f05cdf8be4be35a4afa0ed21d4 45 | 46 | 47 | java-17-openjdk-portable-fastdebug 48 | 17.0.6.0.10 49 | 6.el7openjdkportable 50 | java-17-openjdk-portable-fastdebug-17.0.6.0.10-6.el7openjdkportable 51 | x86_64 52 | 53 | 54 | java-17-openjdk-portable-devel-slowdebug 55 | 17.0.6.0.10 56 | 6.el7openjdkportable 57 | java-17-openjdk-portable-devel-slowdebug-17.0.6.0.10-6.el7openjdkportable 58 | x86_64 59 | 60 | 61 | java-17-openjdk-portable-static-libs-fastdebug 62 | 17.0.6.0.10 63 | 6.el7openjdkportable 64 | java-17-openjdk-portable-static-libs-fastdebug-17.0.6.0.10-6.el7openjdkportable 65 | x86_64 66 | 67 | 68 | java-17-openjdk-portable-static-libs-slowdebug 69 | 17.0.6.0.10 70 | 6.el7openjdkportable 71 | java-17-openjdk-portable-static-libs-slowdebug-17.0.6.0.10-6.el7openjdkportable 72 | x86_64 73 | 74 | 75 | java-17-openjdk-portable 76 | 17.0.6.0.10 77 | 6.el7openjdkportable 78 | java-17-openjdk-portable-17.0.6.0.10-6.el7openjdkportable 79 | x86_64 80 | 81 | 82 | java-17-openjdk-portable-slowdebug 83 | 17.0.6.0.10 84 | 6.el7openjdkportable 85 | java-17-openjdk-portable-slowdebug-17.0.6.0.10-6.el7openjdkportable 86 | x86_64 87 | 88 | 89 | java-17-openjdk-portable-devel-fastdebug 90 | 17.0.6.0.10 91 | 6.el7openjdkportable 92 | java-17-openjdk-portable-devel-fastdebug-17.0.6.0.10-6.el7openjdkportable 93 | x86_64 94 | 95 | 96 | java-17-openjdk-portable-static-libs 97 | 17.0.6.0.10 98 | 6.el7openjdkportable 99 | java-17-openjdk-portable-static-libs-17.0.6.0.10-6.el7openjdkportable 100 | x86_64 101 | 102 | 103 | 104 | openjdk-portable-rhel-7-candidate 105 | 106 | 107 | https://brewhub.engineering.redhat.com/brewhub 108 | http://download.eng.brq.redhat.com/brewroot/packages/ 109 | 110 | http://download.eng.brq.redhat.com/brewroot/packages/java-17-openjdk-portable/17.0.6.0.10/6.el7openjdkportable/src/java-17-openjdk-portable-17.0.6.0.10-6.el7openjdkportable.src.rpm 111 | 112 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/formatters/HtmlFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.formatters; 25 | 26 | import java.io.PrintStream; 27 | import java.util.LinkedList; 28 | import java.util.List; 29 | 30 | public class HtmlFormatter extends StringMappedFormatter { 31 | 32 | public HtmlFormatter(PrintStream stream) { 33 | super(stream); 34 | fillColors(); 35 | } 36 | 37 | @Override 38 | public void print(String s) { 39 | super.print(sanitize(s)); 40 | } 41 | 42 | @Override 43 | public void println(String s) { 44 | super.println(sanitize(s) + "
    "); 45 | } 46 | 47 | private String sanitize(String s) { 48 | if (s == null) { 49 | return null; 50 | } 51 | return s.replaceAll(" ", "  "); 52 | } 53 | 54 | private void fillColors() { 55 | colors.put(SupportedColors.Black, template("black")); 56 | colors.put(SupportedColors.Red, template("red")); 57 | colors.put(SupportedColors.Green, template("green")); 58 | colors.put(SupportedColors.Yellow, template("yellow")); 59 | colors.put(SupportedColors.Blue, template("blue")); 60 | colors.put(SupportedColors.Magenta, template("magenta")); 61 | colors.put(SupportedColors.Cyan, template("cyan")); 62 | colors.put(SupportedColors.LightRed, template("OrangeRed")); 63 | colors.put(SupportedColors.LightGreen, template("LightGreen")); 64 | colors.put(SupportedColors.LightYellow, template("LightYellow")); 65 | colors.put(SupportedColors.LightBlue, template("LightBlue")); 66 | colors.put(SupportedColors.LightMagenta, template("Violet")); 67 | colors.put(SupportedColors.LightCyan, template("LightCyan")); 68 | } 69 | 70 | protected List clossingBuffer = new LinkedList(); 71 | 72 | private String template(String color) { 73 | //keep only one space! see sanitize 74 | return ""; 75 | } 76 | 77 | @Override 78 | public void startBold() { 79 | print(""); 80 | clossingBuffer.add(""); 81 | } 82 | 83 | @Override 84 | public void startColor(SupportedColors color) { 85 | print(getColor(color)); 86 | clossingBuffer.add(""); 87 | } 88 | 89 | @Override 90 | public void reset() { 91 | while (!clossingBuffer.isEmpty()) { 92 | print(clossingBuffer.get(clossingBuffer.size() - 1)); 93 | clossingBuffer.remove(clossingBuffer.size() - 1); 94 | } 95 | } 96 | 97 | @Override 98 | public void initDoc() { 99 | println("
    "); 100 | } 101 | 102 | @Override 103 | public void closeDoc() { 104 | println("
    "); 105 | } 106 | 107 | @Override 108 | public void startTitle2() { 109 | print("

    "); 110 | clossingBuffer.add("

    "); 111 | } 112 | 113 | @Override 114 | public void startTitle4() { 115 | print("

    "); 116 | clossingBuffer.add("

    "); 117 | } 118 | 119 | @Override 120 | public void startTitle3() { 121 | print("

    "); 122 | clossingBuffer.add("

    "); 123 | } 124 | 125 | @Override 126 | public void startTitle1() { 127 | print("

    "); 128 | clossingBuffer.add("

    "); 129 | } 130 | 131 | public void pre(){ 132 | print("
    ");
    133 |     }
    134 | 
    135 |     public void preClose(){
    136 |         print("
    "); 137 | } 138 | 139 | @Override 140 | public void printTable(String[][] table, int rowSize, int columnSize) { 141 | super.println(""); 142 | 143 | // first print the first row definitions 144 | super.println("
      "); 145 | for (int i = 1; i < table[0].length; i++) { 146 | super.println("
    • " + i + ": " + table[0][i] + "
    • "); 147 | table[0][i] = "" + i + ""; // replace the item with its definition (number) 148 | } 149 | super.println("
    "); 150 | 151 | // print the table 152 | super.println(""); 153 | for (int i = 0; i < rowSize; i++) { 154 | super.println(""); 155 | for (int j = 0; j < columnSize; j++) { 156 | if (table[i][j] != null) { 157 | if (table[i][j].equals("X")) { 158 | super.println(""); 159 | } else { 160 | super.println(""); 161 | } 162 | } else { 163 | super.println(""); 164 | } 165 | } 166 | super.println(""); 167 | } 168 | super.println("
    " + table[i][j] + "" + table[i][j] + "
    "); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/formatters/ColorFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 jvanek. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.formatters; 25 | 26 | import java.io.PrintStream; 27 | import java.util.Arrays; 28 | 29 | public class ColorFormatter extends StringMappedFormatter { 30 | //those are NOT spaces but bash \e 31 | 32 | private static final String Default = ""; 33 | 34 | private static final String ResetAll = ""; 35 | 36 | private static final String Bold = ""; 37 | 38 | private static final String Black = ""; 39 | private static final String Red = ""; 40 | private static final String Green = ""; 41 | private static final String Yellow = ""; 42 | private static final String Blue = ""; 43 | private static final String Magenta = ""; 44 | private static final String Cyan = ""; 45 | private static final String LightRed = ""; 46 | private static final String LightGreen = ""; 47 | private static final String LightYellow = ""; 48 | private static final String LightBlue = ""; 49 | private static final String LightMagenta = ""; 50 | private static final String LightCyan = ""; 51 | 52 | private void fillColors() { 53 | colors.put(SupportedColors.Black, Black); 54 | colors.put(SupportedColors.Red, Red); 55 | colors.put(SupportedColors.Green, Green); 56 | colors.put(SupportedColors.Yellow, Yellow); 57 | colors.put(SupportedColors.Blue, Blue); 58 | colors.put(SupportedColors.Magenta, Magenta); 59 | colors.put(SupportedColors.Cyan, Cyan); 60 | colors.put(SupportedColors.LightRed, LightRed); 61 | colors.put(SupportedColors.LightGreen, LightGreen); 62 | colors.put(SupportedColors.LightYellow, LightYellow); 63 | colors.put(SupportedColors.LightBlue, LightBlue); 64 | colors.put(SupportedColors.LightMagenta, LightMagenta); 65 | colors.put(SupportedColors.LightCyan, LightCyan); 66 | } 67 | 68 | public ColorFormatter(PrintStream stream) { 69 | super(stream); 70 | fillColors(); 71 | } 72 | 73 | @Override 74 | public void startBold() { 75 | print(Bold); 76 | } 77 | 78 | @Override 79 | public void startColor(SupportedColors color) { 80 | print(getColor(color)); 81 | } 82 | 83 | @Override 84 | public void reset() { 85 | print(ResetAll); 86 | preset(); 87 | } 88 | 89 | @Override 90 | public void initDoc() { 91 | reset(); 92 | } 93 | 94 | @Override 95 | public void closeDoc() { 96 | print(ResetAll); 97 | } 98 | 99 | private void preset() { 100 | //sets black background and white font 101 | print(""); 102 | print(""); 103 | } 104 | 105 | @Override 106 | public void startTitle2() { 107 | startColor(SupportedColors.Cyan); 108 | } 109 | 110 | @Override 111 | public void startTitle1() { 112 | startColor(SupportedColors.Cyan); 113 | startBold(); 114 | } 115 | 116 | @Override 117 | public void startTitle3() { 118 | startColor(SupportedColors.LightBlue); 119 | } 120 | 121 | @Override 122 | public void startTitle4() { 123 | startColor(SupportedColors.Blue); 124 | } 125 | 126 | @Override 127 | public void printTable(String[][] table, int rowSize, int columnSize) { 128 | // first print the first row definitions 129 | for (int i = 1; i < table[0].length; i++) { 130 | super.println(Bold + i + ") " + ResetAll + table[0][i]); 131 | table[0][i] = Integer.toString(i); // replace the item with its definition (number) 132 | } 133 | 134 | // get the length of the longest item in each column 135 | int[] lengths = new int[table[0].length]; 136 | Arrays.fill(lengths, 0); 137 | for (int i = 0; i < rowSize; i++) { 138 | for (int j = 0; j < columnSize; j++) { 139 | if (table[i][j] != null && table[i][j].length() > lengths[j]) { 140 | lengths[j] = table[i][j].length(); 141 | } 142 | } 143 | } 144 | 145 | // print the table 146 | for (int i = 0; i < rowSize; i++) { 147 | for (int j = 0; j < columnSize; j++) { 148 | int len = 0; 149 | if (table[i][j] != null) { 150 | // print the first row (the numbers) bold 151 | if (i == 0) { 152 | super.print(Bold + table[i][j] + ResetAll + " "); 153 | // Xs will be red 154 | } else if (table[i][j].equals("X")) { 155 | super.print(Red + table[i][j] + ResetAll + " "); 156 | } else { 157 | super.print(table[i][j] + " "); 158 | } 159 | len = table[i][j].length(); 160 | } else { 161 | super.print(" "); 162 | } 163 | // printing spaces to make the table look better 164 | for (int k = len; k < lengths[j]; k++) { 165 | super.print(" "); 166 | } 167 | super.print("| "); 168 | } 169 | super.print("\n"); 170 | } 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/RecreateJckReportSummaries.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff; 25 | 26 | import com.google.gson.GsonBuilder; 27 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 28 | import io.jenkins.plugins.report.jtreg.model.Report; 29 | import io.jenkins.plugins.report.jtreg.model.ReportFull; 30 | import io.jenkins.plugins.report.jtreg.model.Suite; 31 | import io.jenkins.plugins.report.jtreg.model.SuiteTests; 32 | import io.jenkins.plugins.report.jtreg.parsers.JckReportParser; 33 | import java.io.Writer; 34 | import java.nio.charset.StandardCharsets; 35 | import java.nio.file.Files; 36 | import java.nio.file.Path; 37 | import java.nio.file.Paths; 38 | import java.util.List; 39 | import java.util.stream.Collectors; 40 | import java.util.stream.Stream; 41 | 42 | import static io.jenkins.plugins.report.jtreg.Constants.REPORT_JSON; 43 | import static io.jenkins.plugins.report.jtreg.Constants.REPORT_TESTS_LIST_JSON; 44 | import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; 45 | import static java.nio.file.StandardOpenOption.CREATE; 46 | import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; 47 | 48 | public class RecreateJckReportSummaries { 49 | 50 | public static void main(String[] args) throws Exception { 51 | new RecreateJckReportSummaries().work(); 52 | } 53 | 54 | @SuppressFBWarnings(value = {"NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"}, justification = " npe of spotbugs sucks") 55 | private void work() throws Exception { 56 | try (Stream dirsStream = Files.list(Paths.get("").toAbsolutePath().normalize())) { 57 | dirsStream.sequential() 58 | .filter(d -> !Files.isSymbolicLink(d)) 59 | .forEach(this::recreateJckReportSummaryForBuild); 60 | } 61 | } 62 | 63 | @SuppressFBWarnings(value = {"REC_CATCH_EXCEPTION", "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"}, justification = " npe of spotbugs sucks") 64 | private void recreateJckReportSummaryForBuild(Path buildPath) { 65 | Path tckReportsArchive = buildPath.resolve("archive").resolve("tck"); 66 | if (!Files.exists(tckReportsArchive)) { 67 | return; 68 | } 69 | try (Stream tckReportsStream = Files.list(tckReportsArchive)) { 70 | 71 | List suitesList = tckReportsStream.sequential() 72 | .filter(p -> p.toString().endsWith(".xml") || p.toString().endsWith(".xml.gz")) 73 | .map(this::jckReportToSuite) 74 | .filter(s -> s != null) 75 | .collect(Collectors.toList()); 76 | 77 | { 78 | Path summaryPath = buildPath.resolve("jck-" + REPORT_JSON); 79 | if (Files.exists(summaryPath)) { 80 | Files.move(summaryPath, buildPath.resolve("backup_" + "jck-" + REPORT_JSON), REPLACE_EXISTING); 81 | } 82 | List reportShort = suitesList.stream() 83 | .sequential() 84 | .map(s -> new Suite( 85 | s.getName(), 86 | new Report( 87 | s.getReport().getTestsPassed(), 88 | s.getReport().getTestsNotRun(), 89 | s.getReport().getTestsFailed(), 90 | s.getReport().getTestsError(), 91 | s.getReport().getTestsTotal(), 92 | s.getReport().getTestProblems()))) 93 | .sorted() 94 | .collect(Collectors.toList()); 95 | try (Writer out = Files.newBufferedWriter(summaryPath, StandardCharsets.UTF_8, TRUNCATE_EXISTING, CREATE)) { 96 | new GsonBuilder().setPrettyPrinting().create().toJson(reportShort, out); 97 | } 98 | } 99 | { 100 | Path testsListPath = buildPath.resolve("jck-" + REPORT_TESTS_LIST_JSON); 101 | if (Files.exists(testsListPath)) { 102 | Files.move(testsListPath, buildPath.resolve("backup_" + "jck-" + REPORT_TESTS_LIST_JSON), 103 | REPLACE_EXISTING); 104 | } 105 | List suites = suitesList.stream() 106 | .sequential() 107 | .map(s -> new SuiteTests( 108 | s.getName(), 109 | s.getReport() instanceof ReportFull ? ((ReportFull) s.getReport()).getTestsList() : null)) 110 | .sorted() 111 | .collect(Collectors.toList()); 112 | try (Writer out = Files.newBufferedWriter(testsListPath, StandardCharsets.UTF_8, TRUNCATE_EXISTING, 113 | CREATE)) { 114 | new GsonBuilder().create().toJson(suites, out); 115 | } 116 | } 117 | 118 | } catch (Exception ex) { 119 | ex.printStackTrace(); 120 | } 121 | } 122 | 123 | private Suite jckReportToSuite(Path path) { 124 | return new JckReportParser().parsePath(path); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/comparator/FailedTests.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.report.jtreg.main.comparator; 2 | 3 | import io.jenkins.plugins.report.jtreg.BuildReportExtended; 4 | import io.jenkins.plugins.report.jtreg.BuildSummaryParser; 5 | import io.jenkins.plugins.report.jtreg.Constants; 6 | import io.jenkins.plugins.report.jtreg.JckReportPublisher; 7 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.Formatter; 8 | import io.jenkins.plugins.report.jtreg.model.*; 9 | import io.jenkins.plugins.report.jtreg.wrappers.RunWrapperFromDir; 10 | 11 | import java.io.File; 12 | import java.util.*; 13 | 14 | public class FailedTests { 15 | // function for getting failed tests into an ArrayList 16 | private static ArrayList getBuildFailedTests(File build, String exactTestsRegex, Formatter formatter) throws Exception { 17 | ArrayList failedTests = new ArrayList<>(); 18 | 19 | JckReportPublisher jcp = new JckReportPublisher(Constants.IRRELEVANT_GLOB_STRING); // completely irrelevant string 20 | BuildSummaryParser bs = new BuildSummaryParser(Arrays.asList("jck", "jtreg"), jcp); 21 | 22 | BuildReportExtended bex = bs.parseBuildReportExtended(new RunWrapperFromDir(build), null); 23 | SuitesWithResults swr = bex.getAllTests(); 24 | 25 | // since the exception is already handled elsewhere, it checks for it by this and prints the info message 26 | if (swr == null) { 27 | formatter.startColor(Formatter.SupportedColors.Yellow); 28 | formatter.println("The " + Builds.getJobName(build) + " - build:" + Builds.getBuildNumber(build) + " is probably missing some files (may be ABORTED)."); 29 | formatter.reset(); 30 | return failedTests; 31 | } 32 | 33 | for (SuiteTestsWithResults t : swr.getAllTestsAndSuites()) { 34 | for (SuiteTestsWithResults.StringWithResult s : t.getTests()) { 35 | if (s.getStatus().isFailed() && s.getTestName().matches(exactTestsRegex)) { 36 | failedTests.add(s.getTestName()); 37 | } 38 | } 39 | } 40 | 41 | return failedTests; 42 | } 43 | 44 | // function for creating a HashMap of "build info - list of its failed tests" pair 45 | public static HashMap> createFailedMap( 46 | ArrayList buildsToCompare, boolean onlyVolatile, String exactTestsRegex, Formatter formatter) throws Exception { 47 | 48 | HashMap> failedMap = new HashMap<>(); 49 | 50 | for (File build : buildsToCompare) { 51 | failedMap.put(Builds.getJobName(build) 52 | + " - build:" + Builds.getBuildNumber(build) 53 | + " - nvr:" + Builds.getNvr(build), 54 | getBuildFailedTests(build, exactTestsRegex, formatter)); 55 | } 56 | 57 | if (onlyVolatile) { 58 | // get all different tests 59 | Set failedTests = new HashSet<>(); 60 | for (ArrayList tests : failedMap.values()) { 61 | failedTests.addAll(tests); 62 | } 63 | 64 | ArrayList keysFromMap = new ArrayList<>(failedMap.keySet()); 65 | 66 | for (String failedTest : failedTests) { 67 | boolean isEverywhere = true; 68 | for (String key : keysFromMap) { 69 | if (!failedMap.get(key).contains(failedTest)) { 70 | isEverywhere = false; 71 | break; 72 | } 73 | } 74 | 75 | if (isEverywhere) { 76 | for (String key : keysFromMap) { 77 | failedMap.get(key).remove(failedTest); 78 | } 79 | } 80 | } 81 | } 82 | 83 | return failedMap; 84 | } 85 | 86 | // function for reversing the HashMap from reverseFailedMap() method 87 | // Keys: Failed test names, Values: list of builds where the test failed 88 | private static HashMap> reverseFailedMap(HashMap> failedMap) { 89 | HashMap> reversedMap = new HashMap<>(); 90 | 91 | ArrayList allFailed = new ArrayList<>(); 92 | for (ArrayList tests : failedMap.values()) { 93 | for (String test : tests) { 94 | if(!allFailed.contains(test)) { 95 | allFailed.add(test); 96 | } 97 | } 98 | } 99 | 100 | for (String test : allFailed) { 101 | ArrayList testBuilds = new ArrayList<>(); 102 | for (Map.Entry> entry : failedMap.entrySet()) { 103 | if (entry.getValue().contains(test)) { 104 | testBuilds.add(entry.getKey()); 105 | } 106 | } 107 | reversedMap.put(test, testBuilds); 108 | } 109 | 110 | return reversedMap; 111 | } 112 | 113 | // function for getting the HashMap of failed tests ready for printing to console 114 | public static void printFailedTable(HashMap> failedMap, Options.Operations operation, Formatter formatter) { 115 | if (operation == Options.Operations.Compare) { 116 | failedMap = reverseFailedMap(failedMap); 117 | } 118 | 119 | ArrayList allFailedTests = new ArrayList<>(); 120 | for (ArrayList tests : failedMap.values()) { 121 | for (String test : tests) { 122 | if(!allFailedTests.contains(test)) { 123 | allFailedTests.add(test); 124 | } 125 | } 126 | } 127 | Collections.sort(allFailedTests); 128 | 129 | String[][] table = new String[failedMap.size() + 1][allFailedTests.size() + 1]; 130 | // add first line (header) 131 | for (int i = 1; i < allFailedTests.size() + 1; i++) { 132 | table[0][i] = allFailedTests.get(i - 1); 133 | } 134 | // add the builds and tests 135 | ArrayList keys = new ArrayList<>(failedMap.keySet()); 136 | Collections.sort(keys); 137 | 138 | // add the "X"s to the table 139 | int i = 1; 140 | for (String key : keys) { 141 | table[i][0] = key; 142 | for (String test : failedMap.get(key)) { 143 | table[i][allFailedTests.indexOf(test) + 1] = "X"; 144 | } 145 | i++; 146 | } 147 | 148 | formatter.printTable(table, failedMap.size() + 1, allFailedTests.size() + 1); 149 | } 150 | } -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/cmdline/Options.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff.cmdline; 25 | 26 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.ColorFormatter; 27 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.HtmlFormatter; 28 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.PlainFormatter; 29 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.BasicFormatter; 30 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.Formatter; 31 | import io.jenkins.plugins.report.jtreg.main.diff.formatters.HtmlFormatter2; 32 | 33 | import java.io.File; 34 | import java.io.PrintStream; 35 | import java.util.ArrayList; 36 | import java.util.List; 37 | import java.util.regex.Pattern; 38 | 39 | public class Options { 40 | 41 | private boolean skipFailed = true; 42 | private final List dirsToWork; 43 | private boolean fill = false; 44 | private String output_type; 45 | private final List views; 46 | private BasicFormatter formatter; 47 | private PrintStream stream; 48 | private Pattern trackingRegex = Pattern.compile(".*"); 49 | private Pattern trackingRegexChanges = Pattern.compile(".*"); 50 | 51 | public Options() { 52 | this.views = new ArrayList<>(); 53 | this.dirsToWork = new ArrayList<>(); 54 | } 55 | 56 | public List getDirsToWork() { 57 | return dirsToWork; 58 | } 59 | 60 | public boolean hideMisses() { 61 | return views.contains(Arguments.view_hide_misses); 62 | } 63 | 64 | public boolean hideTotals() { 65 | return views.contains(Arguments.view_hide_totals); 66 | } 67 | 68 | public boolean hideNegatives() { 69 | return views.contains(Arguments.view_hide_negatives); 70 | } 71 | 72 | public boolean hidePositives() { 73 | return views.contains(Arguments.view_hide_positives); 74 | } 75 | 76 | public boolean hideValues() { 77 | return views.contains(Arguments.view_info_hidevalues); 78 | } 79 | 80 | public boolean viewInfoSummary() { 81 | return views.isEmpty() || views.contains(Arguments.view_info_summary) || views.contains(Arguments.view_info); 82 | } 83 | 84 | public boolean viewInfoSummarySuites() { 85 | return views.isEmpty() || views.contains(Arguments.view_info_summary_suites) || views.contains(Arguments.view_info); 86 | } 87 | 88 | public boolean viewInfoProblems() { 89 | return views.isEmpty() || views.contains(Arguments.view_info_problems) || views.contains(Arguments.view_info); 90 | } 91 | public boolean viewAllTests() { 92 | return views.isEmpty() || views.contains(Arguments.view_all_tests); 93 | } 94 | 95 | public boolean viewDiffSummary() { 96 | return views.isEmpty() || views.contains(Arguments.view_diff_summary) || views.contains(Arguments.view_diff); 97 | } 98 | 99 | public boolean viewDiffSummarySuites() { 100 | return views.isEmpty() || views.contains(Arguments.view_diff_summary_suites) || views.contains(Arguments.view_diff); 101 | } 102 | 103 | public boolean viewDiffDetails() { 104 | return views.isEmpty() || views.contains(Arguments.view_diff_details) || views.contains(Arguments.view_diff); 105 | } 106 | 107 | public boolean viewDiffList() { 108 | return views.isEmpty() || views.contains(Arguments.view_diff_list) || views.contains(Arguments.view_diff); 109 | } 110 | 111 | void setOutputType(String output_type) { 112 | this.output_type = output_type; 113 | } 114 | 115 | void addView(String nextView) { 116 | views.add(nextView); 117 | } 118 | 119 | void setTrackingRegex(Pattern regex) { 120 | this.trackingRegex=regex; 121 | } 122 | 123 | public Pattern getTrackingRegex() { 124 | return trackingRegex; 125 | } 126 | 127 | void setTrackingRegexChanges(Pattern regex) { 128 | this.trackingRegexChanges=regex; 129 | } 130 | 131 | public Pattern getTrackingRegexChanges() { 132 | return trackingRegexChanges; 133 | } 134 | 135 | public boolean isInfo() { 136 | return (this.viewInfoProblems() || this.viewInfoSummary() || this.viewInfoSummarySuites() || views.contains(Arguments.view_info)); 137 | } 138 | 139 | public boolean isDiff() { 140 | return this.viewDiffDetails() || this.viewDiffList() || this.viewDiffSummary() || this.viewDiffSummarySuites() || views.contains(Arguments.view_diff); 141 | } 142 | 143 | void setFill(boolean b) { 144 | fill = b; 145 | } 146 | 147 | public boolean isFill() { 148 | return fill; 149 | } 150 | 151 | void setSkipFailed(boolean b) { 152 | skipFailed = b; 153 | } 154 | 155 | public boolean isSkipFailed() { 156 | return skipFailed; 157 | } 158 | 159 | boolean add(File file) { 160 | if (skipFailed) { 161 | if (!file.exists() 162 | || JobsRecognition.jobsRecognition().shouldBeSkipped(file)) { 163 | System.err.println("File " + file + " excluded - skipping of failed builds allowed, and it seems to be fialed build"); 164 | return false; 165 | } else { 166 | return addImpl(file); 167 | } 168 | } else { 169 | return addImpl(file); 170 | } 171 | } 172 | 173 | private boolean addImpl(File file) { 174 | if (dirsToWork.size() >= 2) { 175 | if (file.equals(dirsToWork.get(dirsToWork.size() - 1)) && file.equals(dirsToWork.get(dirsToWork.size() - 2))) { 176 | System.err.println("Excluding " + file + " - three same files in row"); 177 | return false; 178 | } 179 | } 180 | dirsToWork.add(file); 181 | System.err.println("Added " + file + " !"); 182 | return true; 183 | } 184 | 185 | public Formatter getFormatter() { 186 | if (formatter == null) { 187 | if (Arguments.output_color.equals(output_type)) { 188 | formatter = new ColorFormatter(stream); 189 | } else if (Arguments.output_html.equals(output_type)) { 190 | formatter = new HtmlFormatter(stream); 191 | } else if (Arguments.output_html2.equals(output_type)) { 192 | formatter = new HtmlFormatter2(stream); 193 | } else { 194 | formatter = new PlainFormatter(stream); 195 | } 196 | } 197 | return formatter; 198 | 199 | } 200 | 201 | public void setStream(PrintStream o) { 202 | this.stream = o; 203 | } 204 | 205 | public PrintStream getStream() { 206 | return stream; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/report/jtreg/main/diff/RecreateJtregReportSummaries.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2023 report-jtreg plugin contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package io.jenkins.plugins.report.jtreg.main.diff; 25 | 26 | import com.google.gson.GsonBuilder; 27 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 28 | import io.jenkins.plugins.report.jtreg.model.Report; 29 | import io.jenkins.plugins.report.jtreg.model.ReportFull; 30 | import io.jenkins.plugins.report.jtreg.model.Suite; 31 | import io.jenkins.plugins.report.jtreg.model.SuiteTests; 32 | import java.io.Writer; 33 | import java.nio.charset.StandardCharsets; 34 | import java.nio.file.Files; 35 | import java.nio.file.Path; 36 | import java.nio.file.Paths; 37 | import java.util.List; 38 | import java.util.stream.Collectors; 39 | import java.util.stream.Stream; 40 | 41 | import static io.jenkins.plugins.report.jtreg.Constants.REPORT_JSON; 42 | import static io.jenkins.plugins.report.jtreg.Constants.REPORT_TESTS_LIST_JSON; 43 | import io.jenkins.plugins.report.jtreg.JtregReportPublisher; 44 | import io.jenkins.plugins.report.jtreg.parsers.JtregReportParser; 45 | import java.io.IOException; 46 | import java.nio.file.FileVisitResult; 47 | import java.nio.file.FileVisitor; 48 | import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; 49 | import static java.nio.file.StandardOpenOption.CREATE; 50 | import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; 51 | import java.nio.file.attribute.BasicFileAttributes; 52 | import java.util.ArrayList; 53 | 54 | public class RecreateJtregReportSummaries { 55 | 56 | public static void main(String[] args) throws Exception { 57 | new RecreateJtregReportSummaries().work(); 58 | } 59 | 60 | @SuppressFBWarnings(value = {"NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"}, justification = " npe of spotbugs sucks") 61 | private void work() throws Exception { 62 | try (Stream dirsStream = Files.list(Paths.get("").toAbsolutePath().normalize())) { 63 | dirsStream.sequential() 64 | .filter(d -> !Files.isSymbolicLink(d)) 65 | .forEach(this::recreateJtregReportSummaryForBuild); 66 | } 67 | } 68 | 69 | @SuppressFBWarnings(value = {"REC_CATCH_EXCEPTION", "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"}, justification = " npe of spotbugs sucks") 70 | private void recreateJtregReportSummaryForBuild(Path buildPath) { 71 | Path tckReportsArchive = buildPath.resolve("archive"); 72 | if (!Files.exists(tckReportsArchive)) { 73 | return; 74 | } 75 | final List archives = new ArrayList<>(); 76 | try { 77 | Files.walkFileTree(buildPath, new FileVisitor() { 78 | @Override 79 | public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 80 | return FileVisitResult.CONTINUE; 81 | } 82 | 83 | @Override 84 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 85 | if (JtregReportPublisher.isJtregArchive(file.toString())) { 86 | archives.add(file); 87 | } 88 | return FileVisitResult.CONTINUE; 89 | } 90 | 91 | @Override 92 | public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { 93 | return FileVisitResult.CONTINUE; 94 | } 95 | 96 | @Override 97 | public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { 98 | return FileVisitResult.CONTINUE; 99 | } 100 | }); 101 | } catch (Exception ex) { 102 | throw new RuntimeException(ex); 103 | } 104 | String prefix = "jtreg"; 105 | try (Stream tckReportsStream = archives.stream()) { 106 | 107 | List suitesList = tckReportsStream.sequential() 108 | .map(this::jtregReportToSuite) 109 | .filter(s -> s != null) 110 | .collect(Collectors.toList()); 111 | 112 | { 113 | Path summaryPath = buildPath.resolve(prefix + "-" + REPORT_JSON); 114 | if (Files.exists(summaryPath)) { 115 | Files.move(summaryPath, buildPath.resolve("backup_" + prefix + "-" + REPORT_JSON), REPLACE_EXISTING); 116 | } 117 | List reportShort = suitesList.stream() 118 | .sequential() 119 | .map(s -> new Suite( 120 | s.getName(), 121 | new Report( 122 | s.getReport().getTestsPassed(), 123 | s.getReport().getTestsNotRun(), 124 | s.getReport().getTestsFailed(), 125 | s.getReport().getTestsError(), 126 | s.getReport().getTestsTotal(), 127 | s.getReport().getTestProblems()))) 128 | .sorted() 129 | .collect(Collectors.toList()); 130 | try (Writer out = Files.newBufferedWriter(summaryPath, StandardCharsets.UTF_8, TRUNCATE_EXISTING, CREATE)) { 131 | new GsonBuilder().setPrettyPrinting().create().toJson(reportShort, out); 132 | } 133 | } 134 | { 135 | Path testsListPath = buildPath.resolve(prefix + "-" + REPORT_TESTS_LIST_JSON); 136 | if (Files.exists(testsListPath)) { 137 | Files.move(testsListPath, buildPath.resolve("backup_" + prefix + "-" + REPORT_TESTS_LIST_JSON), 138 | REPLACE_EXISTING); 139 | } 140 | List suites = suitesList.stream() 141 | .sequential() 142 | .map(s -> new SuiteTests( 143 | s.getName(), 144 | s.getReport() instanceof ReportFull ? ((ReportFull) s.getReport()).getTestsList() : null)) 145 | .sorted() 146 | .collect(Collectors.toList()); 147 | try (Writer out = Files.newBufferedWriter(testsListPath, StandardCharsets.UTF_8, TRUNCATE_EXISTING, 148 | CREATE)) { 149 | new GsonBuilder().create().toJson(suites, out); 150 | } 151 | } 152 | 153 | } catch (Exception ex) { 154 | ex.printStackTrace(); 155 | } 156 | } 157 | 158 | private Suite jtregReportToSuite(Path path) { 159 | return new JtregReportParser().parsePath(path); 160 | } 161 | } 162 | --------------------------------------------------------------------------------