From 51b3c7b298ddeb03f2eadbaa3c163d622681e950 Mon Sep 17 00:00:00 2001 From: Laramie Crocker Date: Sun, 24 Apr 2011 01:05:21 +0000 Subject: [PATCH] CSPACE-3595 Reviving XmlReplay test cases after correcting them for new POX format; taught XmlReplay default xpath to main part of payloads using label element in each test --- .../xmlreplay/ServiceResult.java | 46 ++-- .../xmlreplay/TreeWalkResults.java | 6 + .../xmlreplay/XmlCompareJdom.java | 34 ++- .../IntegrationTests/xmlreplay/XmlReplay.java | 198 +++++------------- .../xmlreplay/XmlReplayTransport.java | 59 ++---- .../test/XmlCompareJdomTest.java | 17 +- .../test-data/xmlreplay/acquisitions/ac1.xml | 2 + .../test-data/xmlreplay/acquisitions/ac2.xml | 2 + .../xmlreplay/acquisitions/acquisitions.xml | 65 ++---- .../xmlreplay/acquisitions/res/ac1.res.xml | 2 + .../xmlreplay/acquisitions/res/ac2.res.xml | 2 + .../xmlreplay/acquisitions/res/ac3.res.xml | 2 + .../acquisitions/res/ac3list.res.xml | 2 + .../test-data/xmlreplay/dev-master.xml | 25 ++- .../test-data/xmlreplay/dimension-master.xml | 4 +- .../test-data/xmlreplay/dimension/1.xml | 16 +- .../test-data/xmlreplay/dimension/2-put.xml | 17 +- .../objectexit/object-exit-display.xml | 23 +- .../xmlreplay/objectexit/object-exit.xml | 34 ++- .../objectexit/res/oePersonDisplayGET.res.xml | 37 ++++ .../test-data/xmlreplay/security.xml | 133 ++++++------ .../xmlreplay/security/6-account-elmo.xml | 1 + .../xmlreplay/xml-replay-master-self-test.xml | 9 +- .../test-data/xmlreplay/xml-replay-master.xml | 18 +- .../services/common/api/Tools.java | 5 + 25 files changed, 362 insertions(+), 397 deletions(-) create mode 100644 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonDisplayGET.res.xml diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java index 70e9a0e20..1604da1ea 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java @@ -45,7 +45,7 @@ public class ServiceResult { public String CSID = ""; public String subresourceCSID = ""; public String requestPayload = ""; //just like requestPayloadRaw, but may have multipart boundary and headers. - public Map requestPayloadsRaw = new HashMap(); + public String requestPayloadsRaw = ""; public String result = ""; public int responseCode = 0; public String responseMessage = ""; @@ -164,23 +164,26 @@ public class ServiceResult { if (overrideExpectedResult){ return true; } - if (Tools.notEmpty(failureReason)){ - return false; - } + //if (Tools.notEmpty(failureReason)){ + // return false; + //} for (Integer oneExpected : expectedCodes){ if (responseCode == oneExpected){ + failureReason = ""; return isDomWalkOK(); } } if ( expectedCodes.size()>0 && codeInSuccessRange(responseCode)){ //none found, but result expected. for (Integer oneExpected : expectedCodes){ if ( ! codeInSuccessRange(oneExpected)){ + failureReason = ""; return isDomWalkOK(); } } } boolean ok = codeInSuccessRange(responseCode); if (ok) { + failureReason = ""; return isDomWalkOK(); } failureReason = " : STATUS CODE UNEXPECTED; "; @@ -188,7 +191,7 @@ public class ServiceResult { } //public static final String[] DUMP_OPTIONS = {"minimal", "detailed", "full"}; - public static enum DUMP_OPTIONS {minimal, detailed, full}; + public static enum DUMP_OPTIONS {minimal, detailed, full, auto}; public static enum PAYLOAD_STRICTNESS {ZERO, ADDOK, TREE, TEXT, TREE_TEXT, STRICT}; @@ -226,6 +229,10 @@ public class ServiceResult { } public String minimal(){ + return minimal(false); + } + + public String minimal(boolean verbosePartsSummary){ return "{" + ( gotExpectedResult() ? "SUCCESS" : "FAILURE" ) + failureReason @@ -237,28 +244,34 @@ public class ServiceResult { +"; URL:"+fullURL +"; auth: "+auth + ( Tools.notEmpty(error) ? "; ERROR:"+error : "" ) - + ( partsSummary(false)) + + (verbosePartsSummary ? partsSummary(true) : partsSummary(false) ) +"}"; } - public String dump(ServiceResult.DUMP_OPTIONS opt){ + public String dump(ServiceResult.DUMP_OPTIONS opt, boolean hasError){ switch (opt){ case minimal: - return minimal(); + return minimal(false); case detailed: return detail(false); case full: return detail(true); + case auto: + return minimal(hasError); default: return toString(); } } /** This method may be called from a test case, using a syntax like ${testID3.resValue("persons_common", "//refName")} */ - public String got(String partName, String xpath) throws Exception { + public String got(String xpath) throws Exception { try { - PayloadLogger.HttpTraffic traffic = PayloadLogger.readPayloads(this.result, this.boundary, this.contentLength); - PayloadLogger.Part partFromServer = traffic.getPart(partName); - String source = partFromServer.getContent(); + //PayloadLogger.HttpTraffic traffic = PayloadLogger.readPayloads(this.result, this.boundary, this.contentLength); + //PayloadLogger.Part partFromServer = traffic.getPart(partName); + //String source = partFromServer.getContent(); + String source = this.result; + if (Tools.isBlank(source)){ + return ""; + } org.jdom.Element element = (org.jdom.Element) XmlCompareJdom.selectSingleNode(source, xpath, null); //todo: passing null for namespace may not work. String sr = element != null ? element.getText() : ""; return sr; @@ -268,14 +281,11 @@ public class ServiceResult { } /** This method may be called from a test case, using a syntax like ${oe9.reqValue("personauthorities_common","//shortIdentifier")} */ - public String sent(String partName, String xpath) throws Exception { + public String sent(String xpath) throws Exception { try { - if (Tools.isEmpty(partName)){ - partName = "default"; - } - String source = this.requestPayloadsRaw.get(partName); + String source = this.requestPayloadsRaw; if (source == null){ - return "ERROR:null:requestPayloadsRaw["+partName+"]"; + return "ERROR:null:requestPayloadsRaw"; } org.jdom.Element element = (org.jdom.Element) XmlCompareJdom.selectSingleNode(source, xpath, null); //e.g. "//shortIdentifier"); //todo: passing null for namespace may not work. String sr = element != null ? element.getText() : ""; diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java index 0d24a169f..b7c10e817 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java @@ -39,6 +39,8 @@ public class TreeWalkResults extends ArrayList { public String rpath = ""; public String ltextTrimmed = ""; public String rtextTrimmed = ""; + public String expected = ""; + public String actual = ""; public String message = ""; public String errmessage = ""; public static enum STATUS {INFO, MATCHED, R_MISSING, R_ADDED, DOC_ERROR, TEXT_DIFFERENT}; @@ -51,8 +53,12 @@ public class TreeWalkResults extends ArrayList { +(Tools.notEmpty(rpath) ? ", R.path:"+rpath : "") +(Tools.notEmpty(message) ? ", message:"+message : "") +(Tools.notEmpty(errmessage) ? ", errmessage:"+errmessage : "") + +", status:"+status +((status != STATUS.MATCHED) && Tools.notEmpty(ltextTrimmed) ? ",\r\n L.trimmed:"+ltextTrimmed : "") +((status != STATUS.MATCHED) && Tools.notEmpty(rtextTrimmed) ? ",\r\n R.trimmed:"+rtextTrimmed : "") + +((status != STATUS.MATCHED) && Tools.notEmpty(expected) ? "\r\nEXPECTED:\r\n------------------\r\n"+expected.trim()+"\r\n------------------" : "") + +((status != STATUS.MATCHED) && Tools.notEmpty(actual) ? "\r\nACTUAL:\r\n------------------\r\n"+actual.trim()+"\r\n------------------\r\n" : "") + +"}"; } diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java index 764e21668..b747cf3cf 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java @@ -60,17 +60,15 @@ private static final String DEFAULT_SAX_DRIVER_CLASS = "org.apache.xerces.parser return doc; } - public static TreeWalkResults compareParts(String expectedContent, String leftID, String actualPartContent, String rightID){ - - System.out.println("expected: \r\n"+expectedContent+"\r\n\r\n"); - System.out.println("ACTUAL: \r\n"+actualPartContent); - + public static TreeWalkResults compareParts(String expectedContent, String leftID, String actualPartContent, String rightID, String startElement){ TreeWalkResults list = new TreeWalkResults(); try { list.leftID = leftID; list.rightID = rightID; TreeWalkResults.TreeWalkEntry infoentry = new TreeWalkResults.TreeWalkEntry(); + infoentry.expected = expectedContent; + infoentry.actual = actualPartContent; infoentry.status = TreeWalkResults.TreeWalkEntry.STATUS.INFO; infoentry.message = "\r\n LEFT file: "+leftID+"\r\n RIGHT file: "+rightID; list.add(infoentry); @@ -87,7 +85,7 @@ private static final String DEFAULT_SAX_DRIVER_CLASS = "org.apache.xerces.parser } else { Document expected = getDocumentFromContent(expectedContent); Document actual = getDocumentFromContent(actualPartContent); - treeWalk(expected, actual, list); + treeWalk(expected, actual, list, startElement); } } catch (Throwable t){ String msg = "ERROR in XmlReplay.compareParts(): "+t; @@ -130,8 +128,28 @@ private static final String DEFAULT_SAX_DRIVER_CLASS = "org.apache.xerces.parser return xpath.selectSingleNode(element); } - public static boolean treeWalk(Document left, Document right, TreeWalkResults list) throws Exception { - boolean res = treeWalk(left.getRootElement(), right.getRootElement(), "/", list); + /* MAYBE DEAL WITH NAMESPACES IN THIS KIND OF APPROACH. + + for (Element el : doc.getRootElement().getDescendants(new ElementFilter())) { + if (el.getNamespace() != null) el.setNamespace(null); + + xpath.addNamespace("x", d.getRootElement().getNamespaceUri()); + */ + public static boolean treeWalk(Document left, Document right, TreeWalkResults list, String startElement) throws Exception { + Element leftElement = left.getRootElement(); + Element rightElement = right.getRootElement(); + if (Tools.notBlank(startElement)) { + XPath xpath = new JDOMXPath(startElement); + Object test = xpath.selectSingleNode(leftElement); + if (test!=null){ + leftElement = (Element)test; + } + Object rtest = xpath.selectSingleNode(rightElement); + if (rtest!=null){ + rightElement = (Element)rtest; + } + } + boolean res = treeWalk(leftElement, rightElement, "/", list); return res; } diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java index ae1a9178e..32eba083c 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java @@ -3,9 +3,7 @@ package org.collectionspace.services.IntegrationTests.xmlreplay; import org.apache.commons.cli.*; import org.apache.commons.io.FileUtils; -import org.apache.commons.jexl2.JexlContext; import org.apache.commons.jexl2.JexlEngine; -import org.apache.commons.jexl2.MapContext; import org.collectionspace.services.common.api.Tools; import org.dom4j.*; import org.dom4j.io.SAXReader; @@ -279,72 +277,26 @@ public class XmlReplay { } private static class PartsStruct { - public List partsList = new ArrayList(); - public List filesList = new ArrayList(); - public List fromTests = new ArrayList(); public List> varsList = new ArrayList>(); - boolean bDoingSinglePartPayload = false; - String singlePartPayloadFilename = ""; + String responseFilename = ""; String overrideTestID = ""; + String startElement = ""; + String label = ""; + public static PartsStruct readParts(Node testNode, final String testID, String xmlReplayBaseDir){ PartsStruct resultPartsStruct = new PartsStruct(); - resultPartsStruct.singlePartPayloadFilename = testNode.valueOf("filename"); - String singlePartPayloadFilename = testNode.valueOf("filename"); - if (Tools.notEmpty(singlePartPayloadFilename)){ - resultPartsStruct.bDoingSinglePartPayload = true; - resultPartsStruct.singlePartPayloadFilename = xmlReplayBaseDir + '/' + singlePartPayloadFilename; + resultPartsStruct.responseFilename = testNode.valueOf("filename"); + resultPartsStruct.startElement = testNode.valueOf("startElement"); + resultPartsStruct.label = testNode.valueOf("label"); + String responseFilename = testNode.valueOf("filename"); + if (Tools.notEmpty(responseFilename)){ + resultPartsStruct.responseFilename = xmlReplayBaseDir + '/' + responseFilename; List varNodes = testNode.selectNodes("vars/var"); readVars(testNode, varNodes, resultPartsStruct); - } else { - resultPartsStruct.bDoingSinglePartPayload = false; - List parts = testNode.selectNodes("parts/part"); - if (parts == null || parts.size()==0){ - //path is just /testGroup/test/part/ - Node part = testNode.selectSingleNode("part"); - readPart(testNode, part, xmlReplayBaseDir, testID, resultPartsStruct); //side-effect: adds objects to result. - } else { - // path is /testGroup/test/parts/part/ - for (Node part : parts){ - readPart(testNode, part, xmlReplayBaseDir, testID, resultPartsStruct); //side-effect: adds objects to result. - } - } } return resultPartsStruct; } - private static void readPart(Node testNode, Node part, String xmlReplayBaseDir, String testID, PartsStruct resultPartsStruct){ - String commonPartName = part.valueOf("label"); - String filename = part.valueOf("filename"); - String fullTestFilename = xmlReplayBaseDir + '/' + filename; - if ( Tools.isEmpty(testID) ){ //if testID is empty, we'll use the *first* filename as ID. - resultPartsStruct.overrideTestID = filename; //It is legal to have a missing ID attribute, and rely on a unique filename. - } - String fromTest = part.valueOf("fromTest"); - if (fromTest == null){ - fromTest = ""; - } - - //These next foun members (partsList,filesList,varsList, and fromTests), - // should be added in lock-step, since they are assumed to exist by index (0,1,2,3, etc.) - resultPartsStruct.partsList.add(commonPartName); - resultPartsStruct.filesList.add(fullTestFilename); - resultPartsStruct.fromTests.add(fromTest); - - List varNodes = part.selectNodes("var"); - readVars(testNode, varNodes, resultPartsStruct); - /* Map vars = new HashMap(); - resultPartsStruct.varsList.add(vars); - List varNodes = part.selectNodes("var"); - //System.out.println("### vars: "+vars.size()+" ########"); - for (Node var: varNodes){ - String ID = var.valueOf("@ID"); - String value = var.getText(); - //System.out.println("ID: "+ID+" value: "+value); - vars.put(ID, value); //vars is already part of resultPartsStruct.varsList - } - //System.out.println("### end-vars ########"); - */ - } private static void readVars(Node testNode, List varNodes, PartsStruct resultPartsStruct){ Map vars = new HashMap(); resultPartsStruct.varsList.add(vars); @@ -404,27 +356,35 @@ public class XmlReplay { } return document; } + protected static String validateResponseSinglePayload(ServiceResult serviceResult, Map serviceResultsMap, PartsStruct expectedResponseParts, XmlReplayEval evalStruct) throws Exception { String OK = ""; - byte[] b = FileUtils.readFileToByteArray(new File(expectedResponseParts.singlePartPayloadFilename)); + byte[] b = FileUtils.readFileToByteArray(new File(expectedResponseParts.responseFilename)); String expectedPartContent = new String(b); Map vars = expectedResponseParts.varsList.get(0); //just one part, so just one varsList. Must be there, even if empty. expectedPartContent = evalStruct.eval(expectedPartContent, serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc); String label = "NOLABEL"; - String leftID = "{from expected part, label:"+label+" filename: "+expectedResponseParts.singlePartPayloadFilename+"}"; + String leftID = "{from expected part, label:"+label+" filename: "+expectedResponseParts.responseFilename+"}"; String rightID = "{from server, label:"+label +" fromTestID: "+serviceResult.fromTestID +" URL: "+serviceResult.fullURL +"}"; + String startElement = expectedResponseParts.startElement; + String partLabel = expectedResponseParts.label; + if (Tools.isBlank(startElement)){ + if (Tools.notBlank(partLabel)) + startElement = "/document/*[local-name()='"+partLabel+"']"; + } TreeWalkResults list = XmlCompareJdom.compareParts(expectedPartContent, leftID, serviceResult.result, - rightID); + rightID, + startElement); serviceResult.addPartSummary(label, list); return OK; } @@ -437,64 +397,14 @@ public class XmlReplay { if (expectedResponseParts == null) return OK; if (serviceResult == null) return OK; if (serviceResult.result.length() == 0) return OK; - String responseDump = serviceResult.result; try { - if (expectedResponseParts.bDoingSinglePartPayload){ - return validateResponseSinglePayload(serviceResult, serviceResultsMap, expectedResponseParts, evalStruct); - } - //System.out.println("responseDump: "+responseDump); - PayloadLogger.HttpTraffic traffic = PayloadLogger.readPayloads(responseDump, serviceResult.boundary, serviceResult.contentLength); - - for (int i=0; i vars = expectedResponseParts.varsList.get(i); - String fromTest = expectedResponseParts.fromTests.get(i); - String expectedPartContent; - if ( ! Tools.isEmpty(fromTest)){ - ServiceResult resultFromTest = serviceResultsMap.get(fromTest); - expectedPartContent = resultFromTest.requestPayloadsRaw.get(label); //TODO: debug this!!!!!!! - } else { - byte[] b = FileUtils.readFileToByteArray(new File(fileName)); - expectedPartContent = new String(b); - expectedPartContent = evalStruct.eval(expectedPartContent, serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc); - } - //System.out.println("expected: "+label+ " content ==>\r\n"+expectedPartContent); - PayloadLogger.Part partFromServer = traffic.getPart(label); - String partFromServerContent = ""; - if (partFromServer != null){ - partFromServerContent = partFromServer.getContent(); - } else { - partFromServerContent = ""; - } - //if (partFromServer!=null) { - //System.out.println("====part content from server. label-->"+label+"<-- \r\npart-->"+partFromServerContent+"<--"); - - String leftID = "{from expected part, label:"+label+" filename: "+fileName+"}"; - String rightID = "{from server, label:"+label - //+" testGroupID: "+serviceResult.testGroupID - +" fromTestID: "+serviceResult.fromTestID - +" URL: "+serviceResult.fullURL - +"}"; - TreeWalkResults list = - XmlCompareJdom.compareParts(expectedPartContent, - leftID, - partFromServerContent, - rightID); - //if (list.getMismatchCount()>0){ - serviceResult.addPartSummary(label, list); - //} - //} - } + return validateResponseSinglePayload(serviceResult, serviceResultsMap, expectedResponseParts, evalStruct); } catch (Exception e){ String err = "ERROR in XmlReplay.validateResponse() : "+e; - //System.out.println(err); return err ; } - return OK; } - //================= runXmlReplayFile ====================================================== public static List runXmlReplayFile(String xmlReplayBaseDir, @@ -537,7 +447,8 @@ public class XmlReplay { } else { authsMapINFO = "Using AuthsMap from control file: "+authsMap; } - System.out.println("XmlReplay running:" + System.out.println("========================================================================" + +"\r\nXmlReplay running:" +"\r\n controlFile: "+ (new File(controlFile).getCanonicalPath()) +"\r\n protoHostPort: "+protoHostPort +"\r\n testGroup: "+testGroupID @@ -545,6 +456,7 @@ public class XmlReplay { +"\r\n AuthsMap: "+authsMapINFO +"\r\n param_autoDeletePOSTS: "+param_autoDeletePOSTS +"\r\n Dump info: "+dump + +"\r\n========================================================================" +"\r\n"); String autoDeletePOSTS = ""; @@ -578,20 +490,12 @@ public class XmlReplay { for (Node testNode : tests) { long startTime = System.currentTimeMillis(); try { - /*try { - //"sleeping 2"); - Thread.currentThread().sleep(2); - } catch (InterruptedException ie){ - System.out.println("ERROR sleeping: "+ie); - } - */ testElementIndex++; String testID = testNode.valueOf("@ID"); String testIDLabel = Tools.notEmpty(testID) ? (testGroupID+'.'+testID) : (testGroupID+'.'+testElementIndex); String method = testNode.valueOf("method"); String uri = testNode.valueOf("uri"); String fullURL = Tools.glue(protoHostPort, "/", uri); - String initURI = uri; String authIDForTest = testNode.valueOf("@auth"); String currentAuthForTest = authsMap.map.get(authIDForTest); @@ -637,20 +541,12 @@ public class XmlReplay { } else if (isPUT) { uri = fromTestID(uri, testNode, serviceResultsMap); } - if (parts.bDoingSinglePartPayload){ - Map vars = null; - if (parts.varsList.size()>0){ - vars = parts.varsList.get(0); - } - serviceResult = XmlReplayTransport.doPOST_PUTFromXML(parts.singlePartPayloadFilename, vars, protoHostPort, uri, method, XmlReplayTransport.APPLICATION_XML, evalStruct, authForTest, testIDLabel); - } else { - boolean POX = true; - if (POX){ - serviceResult = XmlReplayTransport.doPOST_PUTFromXML_POX (parts.filesList, parts.partsList, parts.varsList, protoHostPort, uri, method, evalStruct, authForTest, testIDLabel); - } else { - serviceResult = XmlReplayTransport.doPOST_PUTFromXML_Multipart(parts.filesList, parts.partsList, parts.varsList, protoHostPort, uri, method, evalStruct, authForTest, testIDLabel); - } + Map vars = null; + if (parts.varsList.size()>0){ + vars = parts.varsList.get(0); } + serviceResult = XmlReplayTransport.doPOST_PUTFromXML(parts.responseFilename, vars, protoHostPort, uri, method, XmlReplayTransport.APPLICATION_XML, evalStruct, authForTest, testIDLabel); + results.add(serviceResult); //if (isPOST){ serviceResultsMap.put(testID, serviceResult); //PUTs do not return a Location, so don't add PUTs to serviceResultsMap. @@ -666,7 +562,7 @@ public class XmlReplay { serviceResult.expectedCodes = expectedCodes; } results.add(serviceResult); - if (serviceResult.gotExpectedResult()){ //gotExpectedResult depends on serviceResult.expectedCodes. + if (serviceResult.codeInSuccessRange(serviceResult.responseCode)){ //gotExpectedResult depends on serviceResult.expectedCodes. serviceResultsMap.remove(fromTestID); } } else { @@ -714,28 +610,39 @@ public class XmlReplay { //===================================================== // ALL VALIDATION FOR ALL REQUESTS IS DONE HERE: //===================================================== + boolean hasError = false; String vError = validateResponse(serviceResult, serviceResultsMap, expectedResponseParts, evalStruct); if (Tools.notEmpty(vError)){ serviceResult.error = vError; serviceResult.failureReason = " : VALIDATION ERROR; "; + hasError = true; + } + if (hasError == false){ + hasError = ! serviceResult.gotExpectedResult(); } - String serviceResultRow = serviceResult.dump(dump.dumpServiceResult)+"; time:"+(startTime-System.currentTimeMillis()); + boolean doingAuto = (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.auto); + String serviceResultRow = serviceResult.dump(dump.dumpServiceResult, hasError)+"; time:"+(System.currentTimeMillis()-startTime); String leader = (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.detailed) ? "XmlReplay:"+testIDLabel+": ": ""; + if ( (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.detailed) - || (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.full)){ + || (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.full) ){ System.out.println("\r\n#---------------------#"); } System.out.println(leader+serviceResultRow+"\r\n"); - if (dump.payloads && Tools.notBlank(serviceResult.requestPayload)) { - System.out.println("\r\n========== request payload ==============="); - System.out.println(serviceResult.requestPayload); - System.out.println("==========================================\r\n"); + if (dump.payloads || (doingAuto&&hasError) ) { + if (Tools.notBlank(serviceResult.requestPayload)){ + System.out.println("\r\n========== request payload ==============="); + System.out.println(serviceResult.requestPayload); + System.out.println("==========================================\r\n"); + } } - if (dump.payloads && Tools.notBlank(serviceResult.result)) { - System.out.println("\r\n========== response payload =============="); - System.out.println(serviceResult.result); - System.out.println("==========================================\r\n"); + if (dump.payloads || (doingAuto&&hasError)) { + if (Tools.notBlank(serviceResult.result)){ + System.out.println("\r\n========== response payload =============="); + System.out.println(serviceResult.result); + System.out.println("==========================================\r\n"); + } } } catch (Throwable t) { String msg = "ERROR: XmlReplay experienced an error in a test node: "+testNode+" Throwable: "+t; @@ -754,7 +661,6 @@ public class XmlReplay { return results; } - //======================== MAIN =================================================================== private static Options createOptions() { diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java index 545a2b8f6..292e2d9b6 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java @@ -85,13 +85,12 @@ public class XmlReplayTransport { //System.err.println("ERROR getting content from response: "+t); pr.error = t.toString(); } - - return pr; } public static ServiceResult doDELETE(String urlString, String authForTest, String testID, String fromTestID) throws Exception { ServiceResult pr = new ServiceResult(); + pr.failureReason = ""; pr.method = "DELETE"; pr.fullURL = urlString; pr.fromTestID = fromTestID; @@ -134,6 +133,7 @@ public class XmlReplayTransport { public static final String APPLICATION_XML = "application/xml"; /** Use this overload for multipart messages. */ + /** public static ServiceResult doPOST_PUTFromXML_Multipart(List filesList, List partsList, List> varsList, @@ -169,43 +169,7 @@ public class XmlReplayTransport { String urlString = protoHostPort+uri; return doPOST_PUT(urlString, content, contentRaw, BOUNDARY, method, MULTIPART_MIXED, authForTest, fromTestID); //method is POST or PUT. } - - public static ServiceResult doPOST_PUTFromXML_POX(List filesList, - List partsList, - List> varsList, - String protoHostPort, - String uri, - String method, - XmlReplayEval evalStruct, - String authForTest, - String fromTestID) - throws Exception { - if ( filesList==null||filesList.size()==0 - ||partsList==null||partsList.size()==0 - ||(partsList.size() != filesList.size())){ - throw new Exception("filesList and partsList must not be empty and must have the same number of items each."); - } - //NO: Patrick sez all test files should be complete XML now: StringBuffer content = new StringBuffer("\r\n"); - StringBuffer content = new StringBuffer(); - //content.append(CRLF).append("").append(CRLF); - Map contentRaw = new HashMap(); - for (int i=0; i"); - String urlString = protoHostPort+uri; - String POX_BOUNDARY = "";//empty for POX. - return doPOST_PUT(urlString, content.toString(), contentRaw, POX_BOUNDARY, method,APPLICATION_XML, authForTest, fromTestID); //method is POST or PUT. - } - + */ /** Use this overload for NON-multipart messages, that is, regular POSTs. */ public static ServiceResult doPOST_PUTFromXML(String fileName, @@ -222,8 +186,7 @@ public class XmlReplayTransport { String xmlString = new String(b); xmlString = evalStruct.eval(xmlString, evalStruct.serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc); String urlString = protoHostPort+uri; - Map contentRaw = new HashMap(); - contentRaw.put("default", xmlString); + String contentRaw = xmlString; return doPOST_PUT(urlString, xmlString, contentRaw, BOUNDARY, method, contentType, authForTest, fromTestID); //method is POST or PUT. } @@ -236,9 +199,14 @@ public class XmlReplayTransport { //if (true) return result; //END-HACK - public static ServiceResult doPOST_PUT(String urlString, String content, Map contentRaw, - String boundary, String method, String contentType, - String authForTest, String fromTestID) throws Exception { + public static ServiceResult doPOST_PUT(String urlString, + String content, + String contentRaw, + String boundary, + String method, + String contentType, + String authForTest, + String fromTestID) throws Exception { ServiceResult result = new ServiceResult(); result.method = method; String deleteURL = ""; @@ -299,7 +267,6 @@ public class XmlReplayTransport { return result; } - public static ServiceResult doPOST_PUT_PostMethod(String urlString, String content, Map contentRaw, String boundary, String method, String contentType, String authForTest, String fromTestID) throws Exception { @@ -362,8 +329,6 @@ public class XmlReplayTransport { } finally { rd.close(); } - - } } diff --git a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlCompareJdomTest.java b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlCompareJdomTest.java index 1bf460b02..dbc9c018d 100755 --- a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlCompareJdomTest.java +++ b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlCompareJdomTest.java @@ -99,7 +99,8 @@ public class XmlCompareJdomTest { XmlCompareJdom.compareParts(expectedPartContent, "expected", partFromServer, - "from-server"); + "from-server", + exPARTNAME); assertTreeWalkResults(results,0,0,0,true,true); // addedRight,missingRight,textMismatches,strictMatch,treesMatch } @@ -111,7 +112,8 @@ public class XmlCompareJdomTest { XmlCompareJdom.compareParts(expectedPartContent, "expected", srvHEAD+srvEN2+srvDEPOSITOR+srvFOOT, - "from-server"); + "from-server", + exPARTNAME); assertTreeWalkResults(results,0,0,1,false,true); // addedRight,missingRight,textMismatches,strictMatch,treesMatch } @@ -124,7 +126,8 @@ public class XmlCompareJdomTest { XmlCompareJdom.compareParts(expectedPartContent, "expected", srvHEAD+srvEN+exNEWTREE+srvDEPOSITOR+exNEW+srvFOOT, - "from-server"); + "from-server", + exPARTNAME); assertTreeWalkResults(results,2,0,0,false,false); // addedRight,missingRight,textMismatches,strictMatch,treesMatch @@ -137,7 +140,8 @@ public class XmlCompareJdomTest { XmlCompareJdom.compareParts(exHEAD + exEN_WCH + exNEWTREE + exDEP + exNEW + exFOOT, "expected", partFromServer, - "from-server"); + "from-server", + exPARTNAME); assertTreeWalkResults(results,0,3,0,false,false); // addedRight,missingRight,textMismatches,strictMatch,treesMatch } @@ -149,12 +153,15 @@ public class XmlCompareJdomTest { XmlCompareJdom.compareParts(exHEAD + exDEP + exEN + exFOOT, "expected", partFromServer, - "from-server"); + "from-server", + exPARTNAME); assertTreeWalkResults(results,0,0,0,true,true); // addedRight,missingRight,textMismatches,strictMatch,treesMatch } // ============ expected part, will be used as LEFT tree ========================================================== + private static String exPARTNAME = "objectexit_common"; + private static String exHEAD ="\r\n" +"" +" + @@ -16,5 +17,6 @@ Donor Acquisition Source-1292275630222 + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/ac2.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/ac2.xml index 8cd581fa5..81287aba8 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/ac2.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/ac2.xml @@ -1,4 +1,5 @@ + @@ -16,5 +17,6 @@ xmlns:ns3="http://collectionspace.org/services/acquisition"> Donor Acquisition Source-1292275631503 + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/acquisitions.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/acquisitions.xml index 44cfa508a..479a04d3f 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/acquisitions.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/acquisitions.xml @@ -6,24 +6,19 @@ YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y - + POST /cspace-services/acquisitions/ - - - acquisitions/ac1.xml - + acquisitions/ac1.xml GET /cspace-services/acquisitions/${ac1.CSID} - - - acquisitions/res/ac1.res.xml - + + acquisitions/res/ac1.res.xml @@ -32,10 +27,7 @@ POST /cspace-services/acquisitions/ - - - acquisitions/ac1.xml - + acquisitions/ac1.xml @@ -43,20 +35,15 @@ /cspace-services/acquisitions/${ac1.CSID} - - - acquisitions/res/ac1.res.xml - + + acquisitions/res/ac1.res.xml POST /cspace-services/acquisitions/ - - - acquisitions/ac2.xml - + acquisitions/ac2.xml @@ -64,51 +51,23 @@ /cspace-services/acquisitions/${ac2.CSID} - - - acquisitions/res/ac2.res.xml - + + acquisitions/res/ac2.res.xml - - - - - - DELETE - /cspace-services/acquisitions/8080b6b8-393a-4e8a-b823 - - - DELETE - /cspace-services/acquisitions/231e8787-4d77-4eaf-8d10 - - - DELETE - /cspace-services/acquisitions/cbb82bbc-9513-4f83-ab4f - - - DELETE - /cspace-services/acquisitions/516c2435-4560-408c-8628 - - - diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac1.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac1.res.xml index 7d972ad08..7187217b2 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac1.res.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac1.res.xml @@ -1,4 +1,5 @@ + acquisitionReferenceNumber-1 @@ -16,3 +17,4 @@ + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac2.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac2.res.xml index 0eedfe9f1..21d1a9364 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac2.res.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac2.res.xml @@ -1,4 +1,5 @@ + acquisitionReferenceNumber-1292275631503 @@ -16,4 +17,5 @@ + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3.res.xml index 83994584d..dd7b7a580 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3.res.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3.res.xml @@ -1,4 +1,5 @@ + acquisitionReferenceNumber-1292275630222 @@ -16,4 +17,5 @@ + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3list.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3list.res.xml index fe21664bc..9ab1c0583 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3list.res.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/acquisitions/res/ac3list.res.xml @@ -1,4 +1,5 @@ + @@ -23,5 +24,6 @@ xmlns:ns3="http://collectionspace.org/services/acquisition"> 549dd907-01cd-4f20-aeb7 + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml index 417a01dd6..8d9a52ecf 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml @@ -11,8 +11,8 @@ http://localhost:8180 - - + + YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y @@ -72,12 +72,25 @@ - - --> + + - - + + + + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension-master.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension-master.xml index e887f2f58..4a709dd7b 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension-master.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension-master.xml @@ -2,8 +2,8 @@ http://localhost:8180 - - + + YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/1.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/1.xml index 6867ddfaf..5c84204da 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/1.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/1.xml @@ -1,9 +1,11 @@ - - dimensionType-1288727556164 - entryNumber-1288727556164 - entryDate-1288727556164 - + + + dimensionType-1288727556164 + entryNumber-1288727556164 + entryDate-1288727556164 + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/2-put.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/2-put.xml index 6fa97caee..2edfa4eb5 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/2-put.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dimension/2-put.xml @@ -1,9 +1,10 @@ - - dimensionType-1288727552274 - updated-entryNumber-1288727552274 - updated-entryDate-1288727552274 - - + + + dimensionType-1288727552274 + updated-entryNumber-1288727552274 + updated-entryDate-1288727552274 + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml index efa447bc9..5b5e783b4 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml @@ -30,19 +30,18 @@ GET /cspace-services/personauthorities/${oePersonauthority.CSID}/items/${oePerson.CSID} - + + objectexit/res/oePersonDisplayGET.res.xml + + + ${oePersonGET.got("//csid")} + ${oePersonauthority.CSID} + ${oePerson.sent("//displayName")} + urn:cspace:collectionspace.org:Personauthorities(${oePersonauthority.sent("//shortIdentifier")}):items(foobar)'${oePerson.sent("//displayName")}' + - --> diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit.xml index a1ef45c0c..c0b11cb42 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit.xml @@ -49,11 +49,27 @@ GET /cspace-services/objectexit/${oe1.CSID} - - - objectexit/res/oe2.res.xml + + + + + + + + POST + /cspace-services/objectexit/ + objectexit/oe1.xml + + + GET + /cspace-services/objectexit/${oe1.CSID} + + + objectexit/res/oe2.res.xml + + /document/*[local-name()='objectexit_common'] @@ -89,10 +105,8 @@ /cspace-services/objectexit/${oe1.CSID} - - - objectexit/res/oe2.res.xml - + + objectexit/res/oe2.res.xml @@ -126,10 +140,8 @@ GET /cspace-services/objectexit/${oe1.CSID} - - - objectexit/res/oe2.res.xml - + + objectexit/res/oe2.res.xml diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonDisplayGET.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonDisplayGET.res.xml new file mode 100644 index 000000000..d87e87c69 --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonDisplayGET.res.xml @@ -0,0 +1,37 @@ + + + + + + + + + false + ${inAuthority} + Finbar the DisplayName + + + 1 + 2011-04-23T23:02:16Z + 2011-04-23T23:02:16Z + + + + 6b296c92-bb90-42d8-a804-3ec87c5e21d6 + admin@collectionspace.org + + + 70 + 1aa2c5b8-ce60-412b-bb45-cadba34fab7d + /personauthorities/*/items/*/workflow/ + CRUDL + + + 71 + a7f67d3d-ecee-41a5-9b8d-5a7f89345caa + persons + CRUDL + + + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/security.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/security.xml index 831c48136..b39bb2704 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/security.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/security.xml @@ -7,6 +7,50 @@ YmlnYmlyZDIwMTA6YmlnYmlyZDIwMTA= ZWxtbzIwMTA6ZWxtbzIwMTA= + + + + + POST + /cspace-services/authorization/permissions + security/2-elmo-permission.xml + + + POST + /cspace-services/authorization/permissions/${permElmo.CSID}/permroles + security/10-permissionroles-elmo.xml + + + POST + /cspace-services/accounts + security/6-account-elmo.xml + + + + POST + /cspace-services/dimensions/ + dimension/1.xml + + + 403 + DELETE + dimension1 + + + DELETE + dimension1 + + + DELETE + /cspace-services/authorization/permissions/${permElmo.CSID}/permroles + + + DELETE + accountElmo + + + + @@ -14,10 +58,7 @@ 401,500,501 POST /cspace-services/dimensions/ - - - dimension/1.xml - + dimension/1.xml @@ -75,18 +116,12 @@ POST /cspace-services/dimensions/ - - - dimension/1.xml - + dimension/1.xml PUT /cspace-services/dimensions/${dimension1.CSID} - - - dimension/2-put.xml - + dimension/2-put.xml GET @@ -97,19 +132,13 @@ 403 POST /cspace-services/dimensions/ - - - dimension/1.xml - + dimension/1.xml 403 PUT /cspace-services/dimensions/${dimension1.CSID} - - - dimension/2-put.xml - + dimension/2-put.xml GET @@ -132,7 +161,7 @@ --> - + DELETE /cspace-services/authorization/permissions/${permBigbird.CSID}/permroles @@ -249,19 +269,13 @@ POST /cspace-services/dimensions/ - - - dimension/1.xml - + dimension/1.xml PUT /cspace-services/dimensions/${dimensionBigbird_POST.CSID} - - - dimension/2-put.xml - + dimension/2-put.xml @@ -291,19 +305,13 @@ 403,404 POST /cspace-services/dimensions/ - - - dimension/1.xml - + dimension/1.xml 403,404,405 PUT /cspace-services/dimensions/${dimensionBigbird_POST_AfterPermrolesDeleted.CSID} - - - dimension/2-put.xml - + dimension/2-put.xml 403,404 @@ -335,18 +343,12 @@ POST /cspace-services/dimensions/ - - - dimension/1.xml - + dimension/1.xml PUT /cspace-services/dimensions/${dimensionBigbird_POST_CRU.CSID} - - - dimension/2-put.xml - + dimension/2-put.xml GET @@ -386,19 +388,13 @@ 403,404 POST /cspace-services/dimensions/ - - - dimension/1.xml - + dimension/1.xml 403,404,405 PUT /cspace-services/dimensions/${dimensionBigbird_POST_R.CSID} - - - dimension/2-put.xml - + dimension/2-put.xml GET @@ -413,6 +409,12 @@ + + + Deleting permroles from bigbird2010 + DELETE + /cspace-services/authorization/permissions/${permBigbird.CSID}/permroles + DELETE /cspace-services/accounts/${accountBigbird.CSID}/accountroles @@ -425,6 +427,7 @@ DELETE accountBigbird + - + + YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y - - + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml index 4eb550625..6450c6520 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml @@ -2,8 +2,8 @@ http://localhost:8180 - - + + YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y @@ -24,7 +24,6 @@ - @@ -37,10 +36,19 @@ + --> + + + + + + + - + + + diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java index f2eb1fa5f..4a405fffc 100755 --- a/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java @@ -62,6 +62,11 @@ public class Tools { return !notEmpty(str); } + /** nulls, empty strings, and empty after trim() are considered blank. */ + public static boolean isBlank(String str){ + return !notBlank(str); + } + /** Handles null strings as empty. */ public static boolean notEmpty(String str){ if (str==null) return false; -- 2.47.3