package com.redhat.qe.auto.testng; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; import org.apache.xmlrpc.XmlRpcException; import tcms.API.Session; import tcms.API.TestopiaObject; /** * Example code to retrieve a bugzilla bug's status, given its ID. This is for future use with testng, * so that testng can decide whether to execute a test, based on the group annotation (which may contain * a bug id), and the status of that bug. If the status is ON_QA, for example, it can be tested.<br> * Example Usage: if (BzChecker.getInstance().getBugState("12345") == BzChecker.bzState.ON_QA) {... * @author weissj * */ public class BzChecker { public enum bzState { NEW, ASSIGNED, MODIFIED, ON_DEV, ON_QA, VERIFIED, FAILS_QA, RELEASE_PENDING, POST, CLOSED }; protected static Logger log = Logger.getLogger(BzChecker.class.getName()); protected Bug bug; protected static bzState[] defaultFixedBugStates = new bzState[] { BzChecker.bzState.ON_QA, BzChecker.bzState.VERIFIED, BzChecker.bzState.RELEASE_PENDING, BzChecker.bzState.POST, BzChecker.bzState.CLOSED }; protected static bzState[] fixedBugStates; protected static BzChecker instance = null; private BzChecker() { } private void init() { bug = new Bug(); try { bug.connectBZ(); //read in custom "fixed" bug states if any String fixedStates = System.getProperty("bugzilla.fixedBugStates"); if (fixedStates != null && fixedStates.length() >0) { fixedBugStates = extractStates(fixedStates); } else fixedBugStates = defaultFixedBugStates; }catch(Exception e){ throw new RuntimeException("Could not initialize BzChecker." ,e); } } public static BzChecker getInstance(){ if (instance == null) { instance = new BzChecker(); instance.init(); } return instance; } public bzState getBugState(String bugId) throws XmlRpcException{ return bzState.valueOf(getBugField(bugId, "bug_status").toString()); } public Object getBugField(String bugId, String fieldId) throws XmlRpcException{ /*Object[] bugs = null; try { bugs = bug.getBugs("ids", new Object[] {bugId}); }catch(Exception e){ throw new RuntimeException("Could not retrieve bug " + bugId + " from bugzilla." ,e); } log.finer("Retrieved bugs: " + Arrays.deepToString(bugs)); if (bugs.length ==0) throw new IllegalStateException("No bug found matching ID " + bugId); else if (bugs.length > 1) throw new IllegalStateException("Multiple matches found for bug ID " + bugId); else { Object thisbug = bugs[0]; Map bmap = (Map)thisbug; log.finer("Found bug: " + thisbug.toString() ); Map internals = (Map)bmap.get("internals"); Object fieldValue = internals.get(fieldId); log.finer("Bug field " + fieldId + " of " + bugId + " is " + fieldValue.toString()); return fieldValue; }*/ return bug.getBug(bugId).get(fieldId); } public void setBugState(String bugId, bzState state) { try { bug.update_bug_status(bugId, state); } catch(Exception e){ throw new RuntimeException("Could not set bug status " + bugId + " in bugzilla." ,e); } } public void login(String userid, String password) { try { bug.login(userid, password); } catch(Exception e){ throw new RuntimeException("Could not log in to bugzilla as " + userid ,e); } } public void addComment(String bugId, String comment){ try { bug.add_bug_comment(bugId, comment); } catch(Exception e){ throw new RuntimeException("Could not add comment to bug " + bugId ,e); } } public void addKeywords(String bugId, String... keywords){ editKeywords(bugId, true, keywords); } public void deleteKeywords(String bugId, String... keywords){ editKeywords(bugId, true, keywords); } protected void editKeywords(String bugId, boolean add, String... keywords){ try { Map<String,Object> updates = new HashMap<String,Object>(); updates.put(add?"add_keyword":"delete_keyword", keywords); bug.update_bug(bugId, updates); } catch(Exception e){ throw new RuntimeException("Could not " + (add? "add":"remove") + " keywords for bug " + bugId ,e); } } /** * @param bugId * @return * true (when bug is NOT in any of these states: ON_QA, VERIFIED, RELEASE_PENDING, POST, CLOSED)<br> * false (when IS in any one of these states: ON_QA, VERIFIED, RELEASE_PENDING, POST, CLOSED)<br> * @throws XmlRpcException - when the bug state cannot be determined. */ public boolean isBugOpen(String bugId) throws XmlRpcException { BzChecker.bzState state = getBugState(bugId); for (bzState fixedBugState: fixedBugStates) { if (state.equals(fixedBugState)) return false; } return true; } protected bzState[] extractStates(String states) { String[] splits = states.split(","); List<bzState> list = new ArrayList<bzState>(); for (String state: splits) { list.add(bzState.valueOf(state.trim().toUpperCase())); } return list.toArray(new bzState[] {}); } public class Bug extends TestopiaObject{ private String BZ_URL; //private StringAttribute bug_status = newStringAttribute("bug_status", null); public Bug(){ listMethod = "Bug.get_bugs"; //System.setProperty("bugzilla.url", "https://bugzilla.redhat.com/bugzilla/xmlrpc.cgi"); //System.setProperty("bugzilla.url", "https://bz-web2-test.devel.redhat.com/bugzilla/xmlrpc.cgi"); } protected void connectBZ() throws XmlRpcException, GeneralSecurityException, IOException{ BZ_URL = System.getProperty("bugzilla.url"); session = new Session(System.getProperty("bugzilla.login"), System.getProperty("bugzilla.password"), new URL(BZ_URL)); try { session.init(); // initiate a login here because some bugzilla projects (e.g. Cloud Enablement Tools) are not anonymously // readable which will result in org.apache.xmlrpc.XmlRpcException: You are not authorized to access bug # // when calling lookupBugAndSkipIfOpen. For reliability, we need to login. jsefler 3/16/09 login(System.getProperty("bugzilla.login"), System.getProperty("bugzilla.password")); } catch(Exception e){ log.log(Level.FINE, "Couldn't set up bugzilla connection.", e); } } public int login(String userid, String password) throws XmlRpcException{ Map<String,Object> main = new HashMap<String,Object>(); main.put("login", userid); main.put("password", password); Map map = (Map) this.callXmlrpcMethod("User.login", main); return (Integer)map.get("id"); } public Map<String, Object> getBug(String bugId) throws XmlRpcException{ return (Map) this.callXmlrpcMethod("bugzilla.getBug", bugId); } /* * Returns a Map containing an Array of Maps. Within the innermost Maps (which represent bugs), there's another * Map under the key "internals", which has a key "bug_status". ugh. */ public Object[] getBugs(Map<String, Object> values) throws XmlRpcException { //some Testopia objects have no listing mechanism if(listMethod == null) return null; Map map = (Map) this.callXmlrpcMethod(listMethod, values); return (Object[])map.get("bugs"); //return result; } public Object[] getBugs(String name, Object value) throws XmlRpcException { Map<String, Object> map = new HashMap<String, Object>(); map.put(name, value); return getBugs(map); } public Map update_bug_status(String bug_id, bzState newState) throws XmlRpcException{ Map<String,Object> updates = new HashMap<String,Object>(); updates.put("bug_status", newState.toString()); return update_bug(bug_id, updates); } protected Map update_bug(String bug_id, Map<String,Object> updates)throws XmlRpcException{ Map<String,Object> main = new HashMap<String,Object>(); main.put("updates", updates); main.put("ids", Integer.parseInt(bug_id)); Map map = (Map) this.callXmlrpcMethod("Bug.update", main); //System.out.println(map); return map; } public Map add_bug_comment(String bug_id, String comment) throws XmlRpcException{ Map<String,Object> main = new HashMap<String,Object>(); main.put("id", Integer.parseInt(bug_id)); main.put("comment", comment); Map map = (Map) this.callXmlrpcMethod("Bug.add_comment", main); //Map map = (Map) this.callXmlrpcMethod("bug.add_comment", Integer.parseInt(bug_id), comment); //System.out.println(map); return map; } } public static void main(String[] args) throws Exception{ try { LogManager.getLogManager().readConfiguration(new FileInputStream("/home/jweiss/log.properties")); }catch(Exception e){ System.err.println("Unable to read log config file."); } Properties p = new Properties(); p.load(new FileInputStream("/home/jweiss/automation.properties")); for (Object key: p.keySet()){ System.setProperty((String)key, p.getProperty((String)(key))); } /*Bug myBug = new BzChecker().new Bug(); //List<> myBug.connectBZ(); List<String> ids = new ArrayList<String>(); ids.add("497793"); Object[] bugs = myBug.getBugs("ids",ids); for( Object bug: bugs){ Map bmap = (Map)bug; log.info("Found bug: " + bug.toString() ); Map internals = (Map)bmap.get("internals"); log.info("Bug status is " + internals.get("bug_status")); }*/ BzChecker checker = new BzChecker(); checker.init(); //String id = "497793"; //log.info("State of " + id + " is " + checker.getBugState(id)); //checker.login("jweiss@redhat.com", System.getProperty("bugzilla.password")); //checker.addComment("470058", "test comment"); //checker.setBugState("470058", bzState.ON_QA); //checker.addKeywords("470058", "AutoVerified"); log.info("Keywords: " + checker.getBugField("470058","keywords")); log.info(""+checker.isBugOpen("571833")); } }