package com.redhat.qe.auto.bugzilla; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.xmlrpc.XmlRpcException; import org.testng.ISuite; import org.testng.ISuiteListener; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.SkipException; import org.testng.internal.IResultListener; import com.redhat.qe.auto.tcms.AbstractTestProcedureHandler; import com.redhat.qe.auto.testng.BzBugDependency; import com.redhat.qe.auto.testng.BzChecker; public class BugzillaTestNGListener implements IResultListener, ISuiteListener{ private static final String AUTO_VERIFIED = "AutoVerified"; private static final String BLOCKED_BY_BUG = "blockedByBug"; private static final String VERIFIES_BUG = "verifiesBug"; protected static Logger log = Logger.getLogger(BugzillaTestNGListener.class.getName()); protected static BzChecker bzChecker = null; protected static Map<Object[], BzBugDependency> bzTests = new HashMap<Object[], BzBugDependency>(); protected static HashSet<String> blockingBugs = new HashSet<String>(); @Override public void onConfigurationFailure(ITestResult arg0) { } @Override public void onConfigurationSkip(ITestResult arg0) { } @Override public void onConfigurationSuccess(ITestResult arg0) { } @Override public void onFinish(ITestContext arg0) { } @Override public void onStart(ITestContext arg0) { } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) { } @Override public void onTestFailure(ITestResult arg0) { } @Override public void onTestSkipped(ITestResult arg0) { } protected BzBugDependency getBzData(Object[] params){ for (Object param: params){ if (param instanceof BzBugDependency) return (BzBugDependency)param; } return null; } @Override public void onTestStart(ITestResult result) { if (result.getStatus() == ITestResult.SKIP) return; //don't do anything if the test is skipping already /* * if the test is in a group "blockedByBug-xxxxxx" and the bug is not in * ON_QA, VERIFIED, RELEASE_PENDING, POST, CLOSED then skip it */ bzChecker = BzChecker.getInstance(); String[] groups = result.getMethod().getGroups(); Pattern p = Pattern.compile("[" + VERIFIES_BUG + "|" + BLOCKED_BY_BUG +"]-(\\d+)"); for (String group: groups){ Matcher m = p.matcher(group); if (m.find()){ String number = m.group(1); lookupBugAndSkipIfOpen(number); } } //if nothing found, check the param list (if there is one) for certain types Object[] params = result.getParameters(); BzBugDependency bbb = getBzData(params); if (bbb != null){ String[] bugIds = bbb.getBugIds(); for (String bugId: bugIds) { lookupBugAndSkipIfOpen(bugId); } } } protected void lookupBugAndSkipIfOpen(String bugId){ BzChecker.bzState state; String summary; boolean isBugOpen; try { state = bzChecker.getBugState(bugId); summary = bzChecker.getBugField(bugId, "summary").toString(); isBugOpen = bzChecker.isBugOpen(bugId); } catch(XmlRpcException xre) { log.log(Level.WARNING, "Could not determine the state of Bugzilla bug "+bugId+". Assuming test needs to be run.", xre); return; } // throw a skip exception when the bug is open if (isBugOpen) { //add bug to list of blockers blockingBugs.add(bugId); throw new SkipException("This test is blocked by "+state.toString()+" Bugzilla bug '"+ summary +"'. (https://bugzilla.redhat.com/show_bug.cgi?id="+bugId+")"); } else log.log(Level.INFO, "This test was previously blocked by "+state.toString()+" Bugzilla bug '"+ summary +"'. (https://bugzilla.redhat.com/show_bug.cgi?id="+bugId+")"); } @Override public void onTestSuccess(ITestResult result) { bzChecker = BzChecker.getInstance(); //FIXME this method needs some work //if the test is in a group "verifiesBug-xxxxxx" and the bug is in ON_QA, close it String[] groups = result.getMethod().getGroups(); Pattern p = Pattern.compile("[" + VERIFIES_BUG + "|" + BLOCKED_BY_BUG +"]-(\\d+)"); for (String group: groups){ Matcher m = p.matcher(group); if (m.find()){ String number = m.group(1); BzChecker.bzState state; try { state = bzChecker.getBugState(number); } catch(XmlRpcException xre) { log.log(Level.WARNING, "Could not determine the state of bug " + number + ". It may need to be closed if is hasn't been already.", xre); break; } if (group.startsWith(VERIFIES_BUG)) { log.fine("This test verifies bugzilla bug #"+ number); if (state.equals(BzChecker.bzState.ON_QA)){ //TODO need to call code here to actually close the bug (doesn't work yet) log.warning("Need to verify bug " + number + "!"); /* * not ready to start auto-closing yet * bzChecker.setBugState(number, BzChecker.bzState.VERIFIED); * log.info("Verified bug " + number); **/ verifyComment(result, number); } else log.warning("Bug " + number + " has been verified, but it is in " + state + " state instead of ON_QA"); } else { //blockedByBug log.warning("Test is now unblocked by bug " + number + "."); } } } BzBugDependency blockedOrVerifiedBy = bzTests.get(result.getParameters()); if (blockedOrVerifiedBy != null){ log.warning("Bugs that were previously blocking this test: " + Arrays.deepToString(blockedOrVerifiedBy.getBugIds()) + "."); if (blockedOrVerifiedBy.getType().equals(BzBugDependency.Type.Verifies)){ verifyComment(result, blockedOrVerifiedBy.getBugIds()); } } } @Override public void onFinish(ISuite arg0) { //https://bugzilla.redhat.com/buglist.cgi?bug_id=580127,538160,546399,546397,562302,544353,535788,535806,535576,556928,535327,568917,569563 if (blockingBugs.size() > 0) { Iterator<String> it = blockingBugs.iterator(); StringBuffer sb = new StringBuffer("https://bugzilla.redhat.com/buglist.cgi?bug_id="); while (it.hasNext()){ sb.append(it.next()); if (it.hasNext()) sb.append(","); } log.log(Level.INFO, String.format("There were %d bugs blocking tests in this run: %s", blockingBugs.size(), sb.toString())); } } @Override public void onStart(ISuite arg0) { // TODO Auto-generated method stub } protected void verifyComment(ITestResult result, String... bugNumbers){ for (String bugNumber: bugNumbers) { //first check if this has been tested already. if so, do nothing try { if (bzChecker.getBugField(bugNumber, "keywords").toString().indexOf(AUTO_VERIFIED) != -1 ) { log.info("Bug " + bugNumber + " already has the AutoVerified keyword."); return; } } catch(Exception e) { log.log(Level.WARNING, "Could not determine if bug " + bugNumber + " has been marked AutoVerified yet.",e); } StringBuffer sb = new StringBuffer(); bzChecker.login(System.getProperty("bugzilla.login"), System.getProperty("bugzilla.password")); sb.append("Verified by Automated Test " + result.getName() + " parameters: (" + Arrays.deepToString(result.getParameters()) + ")\n"); String log = AbstractTestProcedureHandler.getActiveLog(); if (log != null) sb.append("Automation log:\n"); sb.append(AbstractTestProcedureHandler.getActiveLog()); bzChecker.addKeywords(bugNumber, AUTO_VERIFIED); bzChecker.addComment(bugNumber, sb.toString()); } bzTests.remove(result.getParameters()); } public static void main (String... args) { Pattern p = Pattern.compile("[verifiesBug|blockedByBug]-(\\d+)"); Matcher m = p.matcher("blockedByBug-12354542"); m.find(); System.out.println(m.group(1)); } }