All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.tck.report.CoverageReport Maven / Gradle / Ivy

The newest version!
package org.hibernate.tck.report;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.hibernate.tck.config.RuntimeProperties;
import org.hibernate.tck.config.Strings;

/**
 * Generates the TCK spec coverage report
 *
 * @author Shane Bryzak
 */
public class CoverageReport {
   
    public enum TestStatus {
        COVERED, UNCOVERED, UNIMPLEMENTED;
    }
   
    public static final String FISHEYE_BASE_URL_PROPERTY = "fisheye_base_url";
   
    public static final String SVN_BASE_URL_PROPERTY = "svn_base_url";
    
    private static final Pattern PATTERN_BOLD = Pattern.compile("([_][^_]*[_])");
    private static final Pattern PATTERN_STRIKETHROUGH = Pattern.compile("([~][^~]*[~])");
    private static final Pattern PATTERN_LITERAL = Pattern.compile("([|][^|]*[|])");
    private static final String REPORT_FILE_NAME = "coverage.html";    
    
    private static final String COLOUR_SHADE_GREEN = "#ddffdd";
    private static final String COLOUR_SHADE_RED = "#ffdddd";
    private static final String COLOUR_SHADE_BLUE = "#80d1ff";
    private static final String COLOUR_SHADE_ORANGE = "#ffcc33";
   
    /*
    * References to the spec assertions made by the tck tests
    */
    private final Map> references;

    private AuditParser auditParser;
        
    private File imageSrcDir;
    private File imageTargetDir;
    
    private RuntimeProperties properties;
    
    private String fisheyeBaseUrl = null;
    
    private String svnBaseUrl = null;
    
    private List unmatched;
    
    private int failThreshold;
    private int passThreshold;
    private Set unimplementedTestGroups;

    public CoverageReport(List references, AuditParser auditParser, File imageSrcDir) {
        this.references = new HashMap>();

        for (SpecReference ref : references) {
            if (!this.references.containsKey(ref.getSection())) {
                this.references.put(ref.getSection(), new ArrayList());
            }

            this.references.get(ref.getSection()).add(ref);
        }

        this.auditParser = auditParser;
        this.imageSrcDir = imageSrcDir;
        this.properties = new RuntimeProperties();
        
        try
        {
           fisheyeBaseUrl = this.properties.getStringValue(FISHEYE_BASE_URL_PROPERTY, null, false);
           
           if (!fisheyeBaseUrl.endsWith("/"))
           {
              fisheyeBaseUrl = fisheyeBaseUrl + "/";
           }
           
           svnBaseUrl = this.properties.getStringValue(SVN_BASE_URL_PROPERTY, null, false);
           
           if (!svnBaseUrl.endsWith("/"))
           {
              svnBaseUrl = svnBaseUrl + "/";
           }
           
           passThreshold = this.properties.getIntValue("pass_threshold", 75, false);
           failThreshold = this.properties.getIntValue("fail_threshold", 50, false);
           
           String unimplemented = this.properties.getStringValue("unimplemented_test_groups", null, false);
           if (unimplemented != null)
           {
              String[] parts = unimplemented.split(",");
              unimplementedTestGroups = new HashSet();
              for (String part : parts)
              {
                 if (!"".equals(part.trim()))
                 {
                    unimplementedTestGroups.add(part.trim());
                 }
              }
           }
        }
        catch (Exception ex)
        {
           // swallow
        }        
    }

    public void generate(File outputDir) throws IOException {
       File coverageFile = new File(outputDir, REPORT_FILE_NAME);
       FileOutputStream out = new FileOutputStream(coverageFile);
       
       imageTargetDir = new File(outputDir, "/images");
       if (!imageTargetDir.exists())
       {
          imageTargetDir.mkdirs();
       }
       
       copyResourceImage("stickynote.png");
       copyResourceImage("blank.png");
       
        calculateUnmatched();
        writeHeader(out);
        writeContents(out);
        writeChapterSummary(out);
        writeSectionSummary(out);
        writeCoverage(out);
        writeUnmatched(out);
        writeFooter(out);
    }
    
    private void copyResourceImage(String filename) throws IOException
    {
       InputStream imageData = this.getClass().getClassLoader().getResourceAsStream("META-INF/" + filename);       
       FileOutputStream out = new FileOutputStream(new File(imageTargetDir, filename));
       try
       {       
          byte[] buffer = new byte[4096];
          int read = imageData.read(buffer);
          while (read != -1)
          {
             out.write(buffer, 0, read);
             read = imageData.read(buffer);
          }
          
          out.flush();
       }
       finally
       {
          out.close();
       }
    }
    
    private void calculateUnmatched()
    {
       unmatched = new ArrayList();

       for (String sectionId : references.keySet()) {
           for (SpecReference ref : references.get(sectionId)) {
               if (!auditParser.hasAssertion(ref.getSection(), ref.getAssertion())) {
                   unmatched.add(ref);
               }
           }
       }       
    }

    private void writeHeader(OutputStream out) throws IOException {
        StringBuilder sb = new StringBuilder();

        sb.append("\n");
        sb.append("\n");
        sb.append("\n");
        sb.append("JSR-299 TCK Coverage Report\n");

        sb.append("\n");

        sb.append("");
        sb.append("

JSR-299 TCK Coverage

"); sb.append("

"); sb.append(auditParser.getVersion()); sb.append("

\n"); out.write(sb.toString().getBytes()); } private void writeContents(OutputStream out) throws IOException { StringBuilder sb = new StringBuilder(); sb.append("

Contents

"); sb.append(""); sb.append(""); sb.append(""); sb.append(""); out.write(sb.toString().getBytes()); } private void writeChapterSummary(OutputStream out) throws IOException { StringBuilder sb = new StringBuilder(); sb.append("

Chapter Summary

\n"); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); boolean odd = true; int totalAssertions = 0; int totalTestable = 0; int totalTested = 0; int totalUnimplemented = 0; int totalImplemented = 0; for (String sectionId : auditParser.getSectionIds()) { // Chapters have no .'s in their id if (sectionId.split("[.]").length == 1) { String prefix = sectionId + "."; int assertions = auditParser.getAssertionsForSection(sectionId).size(); int testable = 0; int implemented = 0; int unimplemented = 0; for (AuditAssertion assertion : auditParser.getAssertionsForSection(sectionId)) { if (assertion.isTestable()) testable++; TestStatus status = getStatus(getCoverageForAssertion(sectionId, assertion.getId())); if (status.equals(TestStatus.COVERED)) { implemented++; } else if (status.equals(TestStatus.UNIMPLEMENTED)) { unimplemented++; } } // Gather stats here for (String subSectionId : auditParser.getSectionIds()) { if (subSectionId.startsWith(prefix)) { assertions += auditParser.getAssertionsForSection(subSectionId).size(); for (AuditAssertion assertion : auditParser.getAssertionsForSection(subSectionId)) { if (assertion.isTestable()) testable++; TestStatus status = getStatus(getCoverageForAssertion(subSectionId, assertion.getId())); if (status.equals(TestStatus.COVERED)) { implemented++; } else if (status.equals(TestStatus.UNIMPLEMENTED)) { unimplemented++; } } } } int tested = implemented + unimplemented; double coveragePercent = testable > 0 ? ((implemented * 1.0) / testable) * 100 : -1; totalAssertions += assertions; totalTestable += testable; totalImplemented += implemented; totalTested += tested; totalUnimplemented += unimplemented; if (odd) { sb.append(""); } else { sb.append(""); } odd = !odd; int margin = (sectionId.split("[.]").length - 1) * 16; sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); if (coveragePercent >= 0) { String bgColor = coveragePercent < failThreshold ? "#ffaaaa" : coveragePercent < passThreshold ? "#ffffaa" : coveragePercent > 100 ? "#FF00CC" : "#aaffaa" ; sb.append(""); } else { sb.append(""); } } sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); double totalCoveragePercent = totalTestable > 0 ? ((totalImplemented * 1.0) / totalTestable) * 100 : -1; if (totalCoveragePercent >= 0) { String bgColor = totalCoveragePercent < failThreshold ? "#ffaaaa" : totalCoveragePercent < passThreshold ? "#ffffaa" : "#aaffaa" ; sb.append(""); } else { sb.append(""); sb.append("
ChapterAssertionsTestableTotal TestedTested
(unimplemented)
Tested
(implemented)
Coverage %
"); sb.append(""); sb.append(sectionId); sb.append(" "); sb.append(auditParser.getSectionTitle(sectionId)); sb.append(""); sb.append(""); sb.append(assertions); sb.append(""); sb.append(testable); sb.append(""); sb.append(tested); sb.append(""); sb.append(unimplemented); sb.append(""); sb.append(implemented); sb.append(""); sb.append(String.format("%.2f%%", coveragePercent)); sb.append(""); } sb.append("
"); sb.append("Total"); sb.append(""); sb.append(totalAssertions); sb.append(""); sb.append(totalTestable); sb.append(""); sb.append(totalTested); sb.append(""); sb.append(totalUnimplemented); sb.append(""); sb.append(totalImplemented); sb.append(""); sb.append(String.format("%.2f%%", totalCoveragePercent)); sb.append(""); } sb.append("
"); out.write(sb.toString().getBytes()); } private void writeSectionSummary(OutputStream out) throws IOException { StringBuilder sb = new StringBuilder(); sb.append("

Section Summary

\n"); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); boolean odd = true; for (String sectionId : auditParser.getSectionIds()) { if (odd) { sb.append(""); } else { sb.append(""); } odd = !odd; int margin = (sectionId.split("[.]").length - 1) * 16; sb.append(""); int assertions = auditParser.getAssertionsForSection(sectionId).size(); int testable = 0; int implemented = 0; int unimplemented = 0; for (AuditAssertion assertion : auditParser.getAssertionsForSection(sectionId)) { if (assertion.isTestable()) testable++; TestStatus status = getStatus(getCoverageForAssertion(sectionId, assertion.getId())); if (status.equals(TestStatus.COVERED)) { implemented++; } else if (status.equals(TestStatus.UNIMPLEMENTED)) { unimplemented++; } } int tested = implemented + unimplemented; double coveragePercent = testable > 0 ? ((implemented * 1.0) / testable) * 100 : -1; sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); if (coveragePercent >= 0) { String bgColor = coveragePercent < failThreshold ? "#ffaaaa" : coveragePercent < passThreshold ? "#ffffaa" : coveragePercent > 100 ? "#FF00CC" : "#aaffaa" ; sb.append(""); } else { sb.append(""); } sb.append("
SectionAssertionsTestableTotal TestedTested
(unimplemented)
Tested
(implemented)
Coverage %
"); sb.append(""); sb.append(sectionId); sb.append(" "); sb.append(auditParser.getSectionTitle(sectionId)); sb.append(""); sb.append(""); sb.append(assertions); sb.append(""); sb.append(testable); sb.append(""); sb.append(tested); sb.append(""); sb.append(unimplemented); sb.append(""); sb.append(implemented); sb.append(""); sb.append(String.format("%.2f%%", coveragePercent)); sb.append(""); } sb.append("
"); out.write(sb.toString().getBytes()); } private void writeCoverage(OutputStream out) throws IOException { out.write("

Coverage Detail

\n".getBytes()); StringBuilder key = new StringBuilder(); key.append(""); key.append(""); key.append(""); key.append(""); key.append(""); key.append(""); key.append("
Colour Key
Assertion is covered
Assertion is not covered
Assertion test is unimplemented
Assertion is untestable
"); out.write(key.toString().getBytes()); for (String sectionId : auditParser.getSectionIds()) { List sectionAssertions = auditParser.getAssertionsForSection(sectionId); if (sectionAssertions != null && !sectionAssertions.isEmpty()) { StringBuilder sb = new StringBuilder(); out.write(("

Section " + sectionId + " - " + escape(auditParser.getSectionTitle(sectionId)) + "

\n").getBytes()); for (AuditAssertion assertion : sectionAssertions) { List coverage = getCoverageForAssertion(sectionId, assertion.getId()); TestStatus status = getStatus(coverage); String divClass = null; if (assertion.isTestable()) { if (status.equals(TestStatus.UNCOVERED)) { divClass = "fail"; } else if (status.equals(TestStatus.UNIMPLEMENTED)) { divClass = "skip"; } else { divClass = "pass"; } } else { divClass = "untestable"; } sb.append("
\n"); if (assertion.isImplied()) { sb.append("The following assertion is not made explicitly by the spec, however it is implied"); } sb.append(" "); sb.append(assertion.getId()); sb.append(")"); if (!Strings.isEmpty(assertion.getNote())) { sb.append(""); //sb.append(""); } sb.append("\n"); sb.append("
"); sb.append("

"); String imageFilename = sectionId + "." + assertion.getId() + ".png"; File imageFile = new File(imageSrcDir, imageFilename); if (imageFile.exists()) { sb.append(""); copyFile(imageFile, new File(imageTargetDir, imageFilename)); } String assertionText = parseStrikethrough(parseBold(parseLiteral(escape(assertion.getText())))); sb.append(assertionText); sb.append("

\n"); if (assertion.isTestable()) { sb.append("
\n"); sb.append("

Coverage

\n"); String currentPackageName = null; if (status.equals(TestStatus.UNCOVERED)) { sb.append("

No tests exist for this assertion

\n"); } else { for (SpecReference ref : coverage) { if (!ref.getPackageName().equals(currentPackageName)) { currentPackageName = ref.getPackageName(); sb.append("
"); sb.append(currentPackageName); sb.append("
\n"); } sb.append("
"); sb.append(ref.getClassName()); sb.append("."); sb.append(ref.getMethodName()); sb.append("()"); if (fisheyeBaseUrl != null) { sb.append("fisheye"); } if (svnBaseUrl != null) { if (fisheyeBaseUrl != null) { sb.append("|"); } sb.append("svn"); } sb.append("
\n"); } } sb.append("
\n"); } else if (!coverage.isEmpty()) { sb.append("A test exists for this untestable assertion!"); } sb.append("
"); } out.write(sb.toString().getBytes()); } else { // We still want to be able to jump to this section by clicking on the links // in the chapter and section summaries out.write(("
\n").getBytes()); } } } private String parseBold(String text) { Matcher m = PATTERN_BOLD.matcher(text); String result = text; while (m.find()) { String replacement = "" + m.group().substring(1, m.group().length() - 1) + ""; result = m.replaceFirst(replacement); m.reset(result); } return result; } private String escape(String value) { return value.replaceAll("<", "<").replaceAll(">", ">"); } private String parseStrikethrough(String text) { Matcher m = PATTERN_STRIKETHROUGH.matcher(text); String result = text; while (m.find()) { String replacement = "" + m.group().substring(1, m.group().length() - 1) + ""; result = m.replaceFirst(replacement); m.reset(result); } return result; } private String parseLiteral(String text) { Matcher m = PATTERN_LITERAL.matcher(text); String result = text; while (m.find()) { String replacement = "" + m.group().substring(1, m.group().length() - 1) + ""; result = m.replaceFirst(replacement); m.reset(result); } return result; } private void writeUnmatched(OutputStream out) throws IOException { if (unmatched.isEmpty()) return; StringBuilder sb = new StringBuilder(); sb.append("

Unmatched tests

\n"); sb.append(String.format("

The following %d tests do not match any known assertions:

", unmatched.size())); sb.append("\n"); sb.append(" \n"); for (SpecReference ref : unmatched) { sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); } sb.append("
SectionAssertionTest ClassTest Method
"); sb.append(ref.getSection()); sb.append(""); sb.append(ref.getAssertion()); sb.append(""); sb.append("
"); sb.append(ref.getPackageName()); sb.append("
"); sb.append(ref.getClassName()); sb.append("
"); sb.append(ref.getMethodName()); sb.append("()"); sb.append("
"); out.write(sb.toString().getBytes()); } private List getCoverageForAssertion(String sectionId, String assertionId) { List refs = new ArrayList(); if (references.containsKey(sectionId)) { for (SpecReference ref : references.get(sectionId)) { if (ref.getAssertion().equals(assertionId)) { refs.add(ref); } } } return refs; } private TestStatus getStatus(List references) { if (references.isEmpty()) { return TestStatus.UNCOVERED; } for (SpecReference reference : references) { if (isImplemented(reference.getGroups())) { return TestStatus.COVERED; } } return TestStatus.UNIMPLEMENTED; } private boolean isImplemented(List groups) { for (String group : groups) { if (unimplementedTestGroups.contains(group)) return false; } return true; } private void writeFooter(OutputStream out) throws IOException { out.write("".getBytes()); out.write("".getBytes()); } private void copyFile(File sourceFile, File targetFile) throws IOException { FileChannel inChannel = new FileInputStream(sourceFile).getChannel(); FileChannel outChannel = new FileOutputStream(targetFile).getChannel(); try { inChannel.transferTo(0, inChannel.size(), outChannel); } catch (IOException e) { throw e; } finally { if (inChannel != null) inChannel.close(); if (outChannel != null) outChannel.close(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy