/* * Copyright 2016 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.domain; import com.thoughtworks.go.util.FileUtil; import com.thoughtworks.go.util.TestFileUtil; import com.thoughtworks.go.util.XpathUtils; import com.thoughtworks.go.work.GoPublisher; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.xpath.XPathExpressionException; import java.io.*; import java.text.MessageFormat; public class UnitTestReportGenerator implements TestReportGenerator { private final File folderToUpload; private GoPublisher publisher; private static Templates templates; private static final Logger LOG = LoggerFactory.getLogger(UnitTestReportGenerator.class); static { try (InputStream xslt = UnitTestReportGenerator.class.getResourceAsStream("unittests.xsl")) { templates = TransformerFactory.newInstance().newTemplates(new StreamSource(xslt)); } catch (Exception e) { LOG.error("Could not load unit test converters", e); } } public UnitTestReportGenerator(GoPublisher publisher, File folderToUpload) { this.publisher = publisher; this.folderToUpload = folderToUpload; } public Properties generate(File[] allTestFiles, String uploadDestPath) { FileOutputStream transformedHtml = null; File mergedResults = new File(folderToUpload.getAbsolutePath() + FileUtil.fileseparator() + TEST_RESULTS_FILE); File mergedResource = null; FileInputStream mergedFileStream = null; try { mergedResource = mergeAllTestResultToSingleFile(allTestFiles); transformedHtml = new FileOutputStream(mergedResults); try { mergedFileStream = new FileInputStream(mergedResource); Source xmlSource = new StreamSource(mergedFileStream); StreamResult result = new StreamResult(transformedHtml); templates.newTransformer().transform(xmlSource, result); } catch (Exception e) { publisher.reportErrorMessage("Unable to publish test properties. Error was " + e.getMessage(), e); } extractProperties(mergedResults); publisher.upload(mergedResults, uploadDestPath); return null; } catch (Exception e) { publisher.reportErrorMessage("Unable to publish test properties. Error was " + e.getMessage(), e); } finally { IOUtils.closeQuietly(mergedFileStream); IOUtils.closeQuietly(transformedHtml); if (mergedResource != null) { mergedResource.delete(); } } return new Properties(); } private Properties extractProperties(File fileSendToServer) throws XPathExpressionException, FileNotFoundException { final Properties properties = new Properties(); addProperty(fileSendToServer, "tests_total_count", TOTAL_TEST_COUNT); addProperty(fileSendToServer, "tests_failed_count", FAILED_TEST_COUNT); addProperty(fileSendToServer, "tests_ignored_count", IGNORED_TEST_COUNT); addProperty(fileSendToServer, "tests_total_duration", TEST_TIME); return properties; } private File mergeAllTestResultToSingleFile(File[] allTestFiles) throws IOException { FileOutputStream mergedResourcesStream = null; try { File mergedResource = TestFileUtil.createUniqueTempFile("mergedFile.xml"); mergedResourcesStream = new FileOutputStream(mergedResource); merge(allTestFiles, mergedResourcesStream); return mergedResource; } finally { IOUtils.closeQuietly(mergedResourcesStream); } } private void addProperty(File xmlFile, String cssClass, String cruiseProperty) { try { String xpath = "//div/p/span[@class='" + cssClass + "']"; String output = XpathUtils.evaluate(xmlFile, xpath); output = output.startsWith(".") ? "0" + output : output; Property property = new Property(cruiseProperty, output); publisher.setProperty(property); } catch (Exception e) { publisher.consumeLine("Could not publish property " + e.getMessage()); } } public void merge(File[] testFiles, OutputStream outputStream) throws IOException { PrintStream out = new PrintStream(outputStream, true, "UTF-8"); out.println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); out.println("<all-results>"); for (File testFile : testFiles) { if (testFile.isDirectory()) { for (Object file : FileUtils.listFiles(testFile, new String[]{"xml"}, true)) { pumpFileContentIfValid(out, (File) file); } } else { pumpFileContentIfValid(out, testFile); } } out.println("</all-results>"); } private void pumpFileContentIfValid(PrintStream out, File testFile) throws IOException { if (!isValidXml(testFile)) { return; } pumpFileContent(testFile, out); } private void pumpFileContent(File file, PrintStream out) throws IOException { BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(file)); String line = bufferedReader.readLine(); if (!line.contains("<?xml")) { // skip prolog out.println(line); } while ((line = bufferedReader.readLine()) != null) { out.println(line); } } finally { IOUtils.closeQuietly(bufferedReader); } } private boolean isValidXml(File file) { try { boolean isTestFile = nodeExists(file, "//test-results") || nodeExists(file, "//testsuite"); if (!isTestFile) { publisher.consumeLine(MessageFormat.format("Ignoring file {0} - it is not a recognised test file.", file.getName())); } return isTestFile; } catch (Exception e) { publisher.consumeLine(MessageFormat.format("The file {0} could not be parsed. It seems to be invalid.", file.getName())); return false; } } private boolean nodeExists(File file, String xpath) { try { return XpathUtils.nodeExists(file, xpath); } catch (Exception ignored) { return false; } } }