/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.jenkins.results.parser; import java.util.ArrayList; import java.util.List; import org.apache.tools.ant.Project; import org.json.JSONArray; import org.json.JSONObject; /** * @author Brian Wing Shun Chan */ public class UnstableMessageUtil { public static String getUnstableMessage(Project project, String buildURL) throws Exception { StringBuilder sb = new StringBuilder(); JSONObject testReportJSONObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL( buildURL + "testReport/api/json")); int failCount = testReportJSONObject.getInt("failCount"); int passCount = 0; int totalCount = 0; if (!testReportJSONObject.has("passCount") && testReportJSONObject.has("totalCount")) { totalCount = testReportJSONObject.getInt("totalCount"); passCount = totalCount - failCount; } else { passCount = testReportJSONObject.getInt("passCount"); totalCount = failCount + passCount; } sb.append("<h6>Job Results:</h6><p>"); sb.append(passCount); sb.append(" Test"); if (passCount != 1) { sb.append("s"); } sb.append(" Passed.<br />"); sb.append(failCount); sb.append(" Test"); if (failCount != 1) { sb.append("s"); } sb.append(" Failed.</p><ol>"); List<String> runBuildURLs = new ArrayList<>(); JSONObject jsonObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL(buildURL + "api/json")); if (jsonObject.has("runs")) { JSONArray runsJSONArray = jsonObject.getJSONArray("runs"); for (int i = 0; i < runsJSONArray.length(); i++) { JSONObject runJSONObject = runsJSONArray.getJSONObject(i); String runBuildURL = runJSONObject.getString("url"); if (!runBuildURL.endsWith( "/" + jsonObject.getInt("number") + "/")) { continue; } JSONObject runBuildURLJSONObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL( runBuildURL + "api/json")); String result = runBuildURLJSONObject.getString("result"); if (!result.equals("SUCCESS")) { runBuildURLs.add(runBuildURL); } } } else { runBuildURLs.add(buildURL); } int failureCount = _getFailureCount(project, runBuildURLs, sb); sb.append("</ol>"); if (failureCount > 3) { sb.append("<p><strong>Click <a href=\""); sb.append(buildURL); sb.append("/testReport/\">here</a> for more failures.</strong>"); sb.append("</p>"); } return sb.toString(); } private static int _getFailureCount( Project project, List<String> runBuildURLs, StringBuilder sb) throws Exception { int failureCount = 0; int firefoxVNCFailureCount = 0; int messageBeginIndex = sb.length(); for (String runBuildURL : runBuildURLs) { JSONObject runBuildURLJSONObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL( runBuildURL + "api/json")); String result = runBuildURLJSONObject.getString("result"); if (result.equals("FAILURE")) { if (failureCount == 3) { failureCount++; sb.append("<li>...</li>"); } if (failureCount < 3) { _getFailureMessage(runBuildURL, sb); } failureCount++; continue; } if (result.equals("UNSTABLE")) { String consoleText = JenkinsResultsParserUtil.toString( JenkinsResultsParserUtil.getLocalURL( runBuildURL + "/consoleText")); System.out.println("loaded."); int cursor = consoleText.indexOf(_FF_VNC_ERROR_MARKER); while (cursor != -1) { firefoxVNCFailureCount++; cursor = consoleText.indexOf( _FF_VNC_ERROR_MARKER, cursor + _FF_VNC_ERROR_MARKER.length()); } } JSONObject testReportJSONObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL( runBuildURL + "testReport/api/json")); JSONArray suitesJSONArray = testReportJSONObject.getJSONArray( "suites"); for (int i = 0; i < suitesJSONArray.length(); i++) { JSONObject suiteJSONObject = suitesJSONArray.getJSONObject(i); JSONArray casesJSONArray = suiteJSONObject.getJSONArray( "cases"); for (int j = 0; j < casesJSONArray.length(); j++) { JSONObject caseJSONObject = casesJSONArray.getJSONObject(j); String status = caseJSONObject.getString("status"); if (status.equals("FIXED") || status.equals("PASSED") || status.equals("SKIPPED")) { continue; } if (failureCount == 3) { failureCount++; sb.append("<li>...</li>"); continue; } if (failureCount > 3) { continue; } sb.append("<li><a href=\""); String runBuildHREF = runBuildURL; runBuildHREF = runBuildHREF.replace("[", "_"); runBuildHREF = runBuildHREF.replace("]", "_"); runBuildHREF = runBuildHREF.replace("#", "_"); sb.append(runBuildHREF); sb.append("/testReport/"); String testClassName = caseJSONObject.getString( "className"); int x = testClassName.lastIndexOf("."); String testPackageName = testClassName.substring(0, x); sb.append(testPackageName); sb.append("/"); String testSimpleClassName = testClassName.substring(x + 1); sb.append(testSimpleClassName); sb.append("/"); String testMethodName = caseJSONObject.getString("name"); String testMethodNameURL = testMethodName; testMethodNameURL = testMethodNameURL.replace("[", "_"); testMethodNameURL = testMethodNameURL.replace("]", "_"); testMethodNameURL = testMethodNameURL.replace("#", "_"); if (testPackageName.equals("junit.framework")) { testMethodNameURL = testMethodNameURL.replace(".", "_"); } sb.append(testMethodNameURL); sb.append("\">"); String jobVariant = JenkinsResultsParserUtil.getJobVariant( runBuildURLJSONObject); if (jobVariant.contains("functional")) { String testName = testMethodName.substring( 5, testMethodName.length() - 1); sb.append(testName); sb.append("</a> - "); sb.append("<a href=\""); String logURL = _getLogURL( jobVariant, project, runBuildURL); sb.append(logURL); sb.append("/"); sb.append(testName.replace("#", "_")); sb.append("/index.html.gz\">Poshi Report</a> - "); sb.append("<a href=\""); sb.append(logURL); sb.append("/"); sb.append(testName.replace("#", "_")); sb.append("/summary.html.gz\">Poshi Summary</a> - "); sb.append("<a href=\""); sb.append(logURL); sb.append( "/jenkins-console.txt.gz\">Console Output</a>"); if (Boolean.parseBoolean( project.getProperty("record.liferay.log"))) { sb.append(" - "); sb.append("<a href=\""); sb.append(logURL); sb.append("/liferay-log.txt.gz\">Liferay Log</a>"); } } else { sb.append(testSimpleClassName); sb.append("."); sb.append(testMethodName); sb.append("</a>"); } sb.append("</li>"); failureCount++; } } } if (firefoxVNCFailureCount > 0) { sb.delete(messageBeginIndex, sb.length()); if (firefoxVNCFailureCount == failureCount) { sb.append("All tests failed due to the Firefox VNC error. "); } else { sb.append(firefoxVNCFailureCount); sb.append(" tests failed due to the Firefox VNC error. "); sb.append(failureCount - firefoxVNCFailureCount); sb.append(" additional tests failed for other reasons. "); } sb.append("See <a href=\"https://issues.liferay.com"); sb.append("/browse/LRQA-28169\">LRQA-28169</a> for more details."); String hostName = JenkinsResultsParserUtil.getHostName("UNKNOWN"); String message = hostName + " VNC Failure"; String from = "root@" + hostName; StringBuilder toSB = new StringBuilder(); toSB.append("kevin.yen@liferay.com, "); toSB.append("kiyoshi.lee@liferay.com, "); toSB.append("leslie.wong@liferay.com, "); toSB.append("michael.hashimoto@liferay.com, "); toSB.append("peter.yoo@liferay.com"); JenkinsResultsParserUtil.sendEmail( message, from, message, toSB.toString()); } return failureCount; } private static void _getFailureMessage( String failureBuildURL, StringBuilder sb) throws Exception { sb.append("<li><strong><a href=\""); sb.append(failureBuildURL); sb.append("\">"); JSONObject failureJSONObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL(failureBuildURL + "api/json")); sb.append( JenkinsResultsParserUtil.fixJSON( failureJSONObject.getString("fullDisplayName"))); sb.append("</a></strong>"); GenericFailureMessageGenerator genericFailureMessageGenerator = new GenericFailureMessageGenerator(); String consoleOutput = JenkinsResultsParserUtil.toString( JenkinsResultsParserUtil.getLocalURL( failureBuildURL + "/logText/progressiveText")); sb.append( genericFailureMessageGenerator.getMessage( failureBuildURL, consoleOutput, null)); sb.append("</li>"); } private static String _getLogURL( String jobVariant, Project project, String runBuildURL) throws Exception { StringBuilder sb = new StringBuilder(); sb.append(project.getProperty("log.base.url")); sb.append("/"); sb.append(project.getProperty("env.MASTER_HOSTNAME")); sb.append("/"); sb.append(project.getProperty("env.TOP_LEVEL_START_TIME")); sb.append("/"); sb.append(project.getProperty("env.JOB_NAME")); sb.append("/"); sb.append(project.getProperty("env.BUILD_NUMBER")); sb.append("/"); sb.append(jobVariant); sb.append("/"); sb.append(JenkinsResultsParserUtil.getAxisVariable(runBuildURL)); return sb.toString(); } private static final String _FF_VNC_ERROR_MARKER = "org.openqa.selenium.WebDriverException: Failed to connect to binary " + "FirefoxBinary"; }