]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-2666 added ObjectExit tests with dom-walk
authorLaramie Crocker <laramie@berkeley.edu>
Sat, 20 Nov 2010 00:17:17 +0000 (00:17 +0000)
committerLaramie Crocker <laramie@berkeley.edu>
Sat, 20 Nov 2010 00:17:17 +0000 (00:17 +0000)
29 files changed:
services/IntegrationTests/pom.xml
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/PayloadLogger.java [new file with mode: 0755]
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java [new file with mode: 0755]
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java [new file with mode: 0755]
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTest.java
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java
services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlCompareJdomTest.java [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe1.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe6.res.xml [deleted file]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe10.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe12.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe14.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe16.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe17.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe2.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe22.res.xml [moved from services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe2.res.xml with 100% similarity, mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe23.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe27.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe28.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe29.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe30.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe6.res.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe8.res.xml [moved from services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe8.res.xml with 100% similarity, mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/security.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml

index c9d8da899c269a472a89a80991b36036a6e937f2..57de764adef30bc20ab3d3e4a253800d66547ea4 100644 (file)
             <artifactId>commons-jexl</artifactId>\r
             <version>2.0.1</version>\r
         </dependency>\r
+        <dependency>\r
+            <groupId>jdom</groupId>\r
+            <artifactId>jdom</artifactId>\r
+            <version>1.0</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
     </dependencies>\r
     \r
     <build>\r
diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/PayloadLogger.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/PayloadLogger.java
new file mode 100755 (executable)
index 0000000..b1259ee
--- /dev/null
@@ -0,0 +1,536 @@
+/**\r
+ * This document is a part of the source code and related artifacts\r
+ * for CollectionSpace, an open source collections management system\r
+ * for museums and related institutions:\r
+ *\r
+ * http://www.collectionspace.org\r
+ * http://wiki.collectionspace.org\r
+ *\r
+ * Copyright (c) 2009 Regents of the University of California\r
+ *\r
+ * Licensed under the Educational Community License (ECL), Version 2.0.\r
+ * You may not use this file except in compliance with this License.\r
+ *\r
+ * You may obtain a copy of the ECL 2.0 License at\r
+ * https://source.collectionspace.org/collection-space/LICENSE.txt\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ */\r
+\r
+package org.collectionspace.services.IntegrationTests.xmlreplay;\r
+\r
+import java.io.*;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+public class PayloadLogger{\r
+\r
+    public static void saveReport(){\r
+        reporter.writeTable();\r
+    }\r
+\r
+    private static Reporter reporter = new Reporter();\r
+\r
+    private static volatile int ID = 1000;\r
+    public String getID(){\r
+        return ""+ID;\r
+    }\r
+\r
+    private static String DD = "--";\r
+    private static String LABEL="LABEL: ";\r
+\r
+    static class Reporter {\r
+        public Reporter(){\r
+            table.append("<html><body><table border='1'>\r\n");\r
+        }\r
+        public static final String START = "<tr><td>";\r
+        public static final String SEP = "</td><td>";\r
+        public static final String END = "</td></tr>";\r
+\r
+        public void writeTable(){\r
+            table.append("</table></body></html>");\r
+            saveFile("./xml/", "results.html", table.toString());\r
+        }\r
+\r
+        private StringBuffer table = new StringBuffer();\r
+\r
+        public synchronized void finished(HttpTraffic traffic){\r
+            String direction = traffic.isRequest ?\r
+                                "<span style='background-color: lightgreen;'>==&gt;</span>"\r
+                                :\r
+                                " &lt;==";\r
+            table.append(START)\r
+                    .append(direction)\r
+                    .append(SEP)\r
+                    .append(traffic==null ? "null" : traffic.toRow(SEP, this))\r
+                    .append(END);\r
+        }\r
+\r
+        public synchronized void finished(List<HttpTraffic> trafficList){\r
+            for (HttpTraffic traffic: trafficList){\r
+                finished(traffic);\r
+            }\r
+        }\r
+\r
+        public static String link(String desc, String url){\r
+            return "<a href='"+url+"'>"+desc+"</a>";\r
+        }\r
+        public static final String newline = "<br />\r\n";\r
+\r
+    }\r
+\r
+\r
+    static class HttpTraffic {\r
+        public HttpTraffic(){\r
+            payloads = new ArrayList<Part>();\r
+        }\r
+        public List<Part> payloads;\r
+        public String method = "";\r
+        public String url = "";\r
+        public String queryParams = "";\r
+        public String message = "";\r
+        public int responseCode = 0;\r
+        public String boundary = "";\r
+        public String location = "";\r
+        public long contentLength = -1;\r
+        public boolean isRequest = true;\r
+        public boolean extra = false;\r
+        public String ID = "0";\r
+        public int nexti = 0;\r
+\r
+        public Part getPart(String label){\r
+            for (Part part : payloads){\r
+                if (part.label.equalsIgnoreCase(label)){\r
+                    return part;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public String toRow(String sep, Reporter reporter){\r
+            StringBuffer b = new StringBuffer();\r
+            for (Part part : payloads){\r
+                String name = part.label;\r
+                if (part.filename.length()==0){\r
+                    continue;\r
+                }\r
+                if (name.trim().length()<=0){\r
+                    name = ID;\r
+                }\r
+                name = name+" ("+part.filetype+')';\r
+                String link = reporter.link(name, part.filename);\r
+                b.append(link)\r
+                 .append(reporter.newline);\r
+            }\r
+            String parts = b.toString();\r
+            if (isRequest){\r
+                return  ID+sep\r
+                        +method+sep\r
+                        +url+sep\r
+                        +queryParams+sep\r
+                        +sep\r
+                        +parts;\r
+            } else {\r
+                return  ID+sep\r
+                        +responseCode+sep\r
+                        +message+sep\r
+                        +location+sep\r
+                        +contentLength+sep\r
+                        +url\r
+                        +parts;\r
+            }\r
+        }\r
+    }\r
+\r
+    static class Part {\r
+        public Part(String boundary){\r
+            this.boundary = boundary;\r
+        }\r
+        public boolean isMultipart(){\r
+            return boundary.length()>0;\r
+        }\r
+        public String toString(){\r
+            return "Part:"+label+";";\r
+        }\r
+        public String filename = "";\r
+        public String filetype = "";\r
+        public String boundary;\r
+        public StringBuffer buffer = new StringBuffer();\r
+        public String getContent(){\r
+            return buffer.toString();\r
+        }\r
+        public String label = "";\r
+        public int readPart(String[]lines, int i){\r
+            String line = "";\r
+            boolean readingPartHeaders = true;\r
+            while(readingPartHeaders){\r
+                line = killTrailingWS(lines[i]);\r
+                if (line.toUpperCase().startsWith(LABEL)){\r
+                    this.label = line.substring(LABEL.length()).trim();\r
+                } else if (line.trim().length()==0){\r
+                    readingPartHeaders = false;\r
+                }\r
+                i++;\r
+            }\r
+            while (i<lines.length){\r
+                line = lines[i];\r
+                if (line.startsWith(DD+boundary)){\r
+                    return i;   \r
+                }\r
+                this.buffer.append(line).append("\r\n");   //todo: maybe don't add CRLF on last line.\r
+                i++;\r
+            }\r
+            return i;               \r
+        }\r
+        public int readRemaining(String [] lines, int i, long contentLength){\r
+            String line;\r
+            int bytesRead=0;\r
+            while (i<lines.length && bytesRead<contentLength){\r
+                line = killTrailingWS(lines[i]);\r
+                if (line.startsWith("HTTP/1.1")){\r
+                    return i;\r
+                }\r
+                int read = line.length();\r
+                bytesRead += read;\r
+                buffer.append(line).append("\r\n");   //todo: maybe don't add CRLF on last line.\r
+                i++;\r
+            }\r
+            return i;\r
+        }\r
+    }\r
+\r
+    public static String parseBoundary(String headerLine) {\r
+        if (Tools.isEmpty(headerLine)) {\r
+            return "";\r
+        }\r
+        String lineUP = headerLine.toUpperCase();\r
+        String boundary = "";\r
+        if (lineUP.startsWith("CONTENT-TYPE:")) {\r
+            String[] boundaryTokens = headerLine.split("boundary=");\r
+            if (boundaryTokens.length == 2) {\r
+                boundary = killTrailingWS(boundaryTokens[1]);\r
+\r
+            } else if (boundaryTokens.length > 2) {\r
+                System.err.println("WARNING: too many tokens after boundary= on Content-Type: header line: " + headerLine);\r
+            }\r
+        }\r
+        return boundary;\r
+    }\r
+\r
+    /** places the boundary on the HttpTraffic in parameter object if boundary found in header "Content-Type:".\r
+     *  @return the index of the NEXT line the caller should read. */\r
+    protected static int readHeaders(HttpTraffic traffic, String[]lines, int i){\r
+        int lineCount = lines.length;\r
+        String line, lineUP;\r
+        // Now read headers until we are ready for payload or parts.\r
+        while (i<lineCount){\r
+            line = lines[i];\r
+            if (line.trim().length()==0){  //blank line seen: end of headers.\r
+                i++;\r
+                break;\r
+            } else {  //still reading outer headers.\r
+                lineUP = line.toUpperCase().trim();\r
+                if (lineUP.startsWith("CONTENT-TYPE:")){\r
+                    String[] boundaryTokens = line.split("boundary=");\r
+                    if (boundaryTokens.length == 2){\r
+                        traffic.boundary = killTrailingWS(boundaryTokens[1]);\r
+\r
+                    } else if (boundaryTokens.length > 2){\r
+                        System.err.println("WARNING: too many tokens after boundary= on Content-Type: header line: "+line);\r
+                    }\r
+                } else if (lineUP.startsWith("LOCATION: ")){\r
+                    traffic.location = killTrailingWS(line.substring("LOCATION: ".length()));\r
+                } else if (lineUP.startsWith("CONTENT-LENGTH: ")){\r
+                    traffic.contentLength = Integer.parseInt(killTrailingWS(line.substring("CONTENT-LENGTH: ".length())));\r
+                }\r
+                i++;\r
+            }\r
+        }\r
+        return i;\r
+    }\r
+\r
+\r
+    //  0  1  2  3\r
+    //  a  b  c  \r\r
+\r
+    private static String killTrailingWS(String s){\r
+        int i = s.length();\r
+        while (i>0){\r
+            char c = s.charAt(i-1);\r
+            if (c=='\r' || c=='\n' || c==' '){\r
+                i--;\r
+                continue;\r
+            } else {\r
+                break;\r
+            }\r
+        }\r
+        return s.substring(0, i);\r
+    }\r
+\r
+    public static HttpTraffic readPayloads(String fullPayload, String boundary, long contentLength){\r
+        HttpTraffic traffic = new HttpTraffic();\r
+        traffic.contentLength = contentLength;\r
+        traffic.boundary = boundary;\r
+        String [] lines = fullPayload.split("\\n", -1);\r
+        readPayloads(traffic, lines, 0);\r
+        return traffic;\r
+    }\r
+\r
+    protected static int readPayloads(HttpTraffic traffic, String[]lines, int i){\r
+        if (traffic.boundary.length()<=0){   //END of headers, and no boundary, so read remaining and return.\r
+            if (traffic.contentLength == 0){\r
+                return i;\r
+            }\r
+            Part part = new Part("");\r
+            traffic.payloads.add(part);\r
+            i = part.readRemaining(lines, i, traffic.contentLength);\r
+            return i;\r
+        }\r
+        int lineCount = lines.length;\r
+        String line;\r
+        while (i<lineCount){\r
+            //rest of message is payloads.\r
+            line = lines[i];\r
+\r
+            if (line.startsWith( DD + traffic.boundary + DD )){   //this is the ending boundary.\r
+                //close and accept payload chunk.\r
+                i++;  //bump past last boundary.  There might be more traffic after this.\r
+                return i;\r
+            } else if (line.startsWith(DD + traffic.boundary)){   //this is a first or middle boundary, but not last boundary.\r
+                i++;  //bump past boundary\r
+                //begin payload chunk\r
+                Part part = new Part(traffic.boundary);\r
+                traffic.payloads.add(part);\r
+                i = part.readPart(lines, i);\r
+            } else {\r
+                return i;\r
+                //if (line.trim().length()>0){\r
+                //    System.err.println("********** Skipping line: "+line); //either parser error, or something is outside of a boundary.\r
+                //}\r
+                //i++;\r
+            }\r
+        }\r
+        return i;\r
+    }\r
+\r
+         \r
+    private HttpTraffic parseForward(String forward, int nexti){\r
+        HttpTraffic forwardTraffic = new HttpTraffic();\r
+        forwardTraffic.isRequest = true;\r
+        forwardTraffic.ID = getID();\r
+        //String[] lines = forward.split("\\r\\n", -1);\r
+        String[] lines = forward.split("\\n", -1);\r
+        int lineCount = lines.length;\r
+        String line;\r
+        int i = nexti;\r
+\r
+        // Read the first line, and figure out if GET, POST, etc., and the URI\r
+        line = lines[i];\r
+        while (line.trim().length()==0){\r
+            i++;\r
+            if (i>=lineCount-1){\r
+                return null;\r
+            }\r
+            line = lines[i];\r
+        }\r
+        String[] tokens = line.split(" ", -1);\r
+        forwardTraffic.method = tokens[0];\r
+        String urlString = tokens[1];\r
+        String[] urlHalves = urlString.split("\\?", -1); //look for a query string of the form /foo/bar?param=baz and break on question mark.\r
+        forwardTraffic.url = urlHalves[0];\r
+        if (urlHalves.length > 1){\r
+            forwardTraffic.queryParams = urlHalves[1];\r
+        }\r
+        i++;\r
+\r
+        //if (forwardTraffic.method.equals("GET")|| forwardTraffic.method.equals("DELETE")){\r
+        //    return forwardTraffic;\r
+        //}\r
+        // Now read headers until we are ready for payload or parts.\r
+        i = readHeaders(forwardTraffic, lines, i);\r
+\r
+        /*\r
+        if ( (i<lines.length-1) && (forwardTraffic.contentLength<=0) ) {  //0 means a 0 was seen, -1 means no header was seen, as will be the case in GET or DELETE.\r
+\r
+            //there are more lines, but content-length header was zero,\r
+            // this means we are getting keep-alive bunches of DELETEs or OKs back.\r
+            System.err.println("###### extra requests in this one."+getID());\r
+            String filename = getID()+'_'+forwardTraffic.method+'_'+forwardTraffic.url.replaceAll("/", "_")+".requests";\r
+            saveFile("./xml", filename, forward);\r
+            return forwardTraffic;\r
+        }\r
+        */\r
+\r
+        // We are past headers now. The rest of message is payloads.\r
+        i = readPayloads(forwardTraffic, lines, i);  //messes with forwardTraffic and places parts in it.\r
+        forwardTraffic.nexti = i;\r
+        return forwardTraffic;\r
+    }\r
+\r
+    private HttpTraffic parseReverse(String reverse, int nexti){\r
+        HttpTraffic reverseTraffic = new HttpTraffic();\r
+        reverseTraffic.isRequest = false;\r
+        reverseTraffic.ID = getID();\r
+        //String[] lines = reverse.split("\\r\\n", -1);\r
+        String[] lines = reverse.split("\\n", -1);\r
+        int lineCount = lines.length;\r
+        String line;\r
+        int i = nexti;\r
+        if (i>=lineCount){\r
+            return null;\r
+        }\r
+        line = lines[i];\r
+                   \r
+        // Read the first line, and figure out response code, message.\r
+        while (i<lineCount){\r
+            if (line.startsWith("HTTP/1.1")){\r
+                break;\r
+            }\r
+            i++;\r
+            line = lines[i];\r
+        }\r
+        String[] tokens = line.split(" ", 3);\r
+        String HTTP11 = tokens[0];\r
+        reverseTraffic.responseCode = Integer.parseInt(tokens[1]);\r
+        reverseTraffic.message = killTrailingWS(tokens[2]);\r
+        i++;  // done reading first line. Bump past first line.\r
+\r
+        //if (forwardResult.message.equals("OK")){\r
+        //    return forwardResult;\r
+        //}\r
+\r
+        // Now read headers until we are ready for payload or parts.\r
+        i = readHeaders(reverseTraffic, lines, i);\r
+\r
+        /*\r
+        if ( (i<lines.length-1) && (reverseTraffic.contentLength==0) ) {\r
+            //there are more lines, but content-length header was zero,\r
+            // this means we are getting keep-alive bunches of DELETEs or OKs back.\r
+            System.err.println("###### extra responses in this one."+id);\r
+            String filename = getID()+".reponses";\r
+            saveFile("./xml", filename, reverse);\r
+            reverseTraffic.extra = true;\r
+            return reverseTraffic;\r
+        }\r
+        */\r
+        // We are past headers now. The rest of message is payloads.\r
+        i = readPayloads(reverseTraffic, lines, i);  //messes with forwardResult and places parts in it.\r
+        reverseTraffic.nexti = i;\r
+        if (i>=lineCount){\r
+            reverseTraffic.nexti = -1;\r
+        }\r
+        return reverseTraffic;\r
+    }\r
+\r
+    private List<HttpTraffic> handleTcpDump(String dump){\r
+        int i = 0;\r
+        int trafficID = 0;\r
+        List<HttpTraffic> trafficList = new ArrayList<HttpTraffic>();\r
+        while (i>-1){\r
+            trafficID++;\r
+            HttpTraffic forward = parseForward(dump, i);\r
+            if (forward==null) break;\r
+            i = forward.nexti;\r
+            forward.ID = ""+trafficID;\r
+            if (forward.payloads.size()>0){\r
+                saveForwardFiles(forward);\r
+            }\r
+            trafficList.add(forward);\r
+\r
+            HttpTraffic reverse = parseReverse(dump, i);\r
+            if (reverse==null) break;\r
+            reverse.ID = ""+trafficID;\r
+            i = reverse.nexti;\r
+            if (reverse.payloads.size()>0){\r
+                saveReverseFiles(reverse);\r
+            }\r
+            trafficList.add(reverse);\r
+        }\r
+        return trafficList;\r
+    }\r
+\r
+    public static File saveFile(String dir, String relativeName, String content){\r
+        File result = null;\r
+        PrintWriter writer;\r
+        try{\r
+            result = new File(dir, relativeName);\r
+            writer = new PrintWriter(new FileOutputStream(result));\r
+        }catch (Exception e){\r
+            System.out.println("Can't write to file in saveFile: " + relativeName + "  \r\n" + e);\r
+            return null;\r
+        }\r
+        writer.write(content);\r
+        writer.close();\r
+        return result;\r
+    }\r
+    \r
+    private void saveForwardFiles(HttpTraffic fr){\r
+        for (Part part : fr.payloads){\r
+            String body = part.buffer.toString();\r
+            if (body.trim().length()==0){\r
+                continue;\r
+            }\r
+            String filename = fr.ID+'_'+fr.method+'_'+fr.url.replaceAll("/", "_")+'_'+part.label+".xml";\r
+            filename = filename.replaceAll("/", "_");\r
+            System.out.println("trying to save file: "+filename+" :: "+fr);\r
+            part.filename = filename;\r
+            saveFile("./xml", filename, body);\r
+        }\r
+    }\r
+    \r
+    private void saveReverseFiles(HttpTraffic fr){\r
+        for (Part part : fr.payloads){\r
+            String body = part.buffer.toString();\r
+            if (body.trim().length()==0){\r
+                continue;\r
+            }\r
+            String filename = fr.ID+'_'+fr.method+'_'+fr.url.replaceAll("/", "_");\r
+            if (part.label.length()==0){\r
+                if (body.trim().startsWith("<?xml")){\r
+                    filename = filename + "_res.xml";\r
+                    part.filetype = "xml";\r
+                } else {\r
+                    filename = filename + "_res.txt";\r
+                    part.filetype = "txt";\r
+                }\r
+            } else {\r
+                filename = filename + '_'+part.label+"_res.xml";\r
+                part.filetype = "xml";\r
+            }\r
+            filename = filename.replaceAll("/", "_");\r
+            System.out.println("trying to save file: "+filename+" :: "+fr);\r
+            part.filename = filename;\r
+            saveFile("./xml", filename, body);\r
+        }\r
+    }\r
+\r
+    public static String readFile(String dir, String relPath) throws Exception{\r
+        File theFile = new File(dir, relPath);\r
+        FileInputStream fis = new FileInputStream(theFile);\r
+        byte[] theData = new byte[(int) theFile.length()];\r
+        // need to check the number of bytes read here\r
+        int howmany = fis.read(theData);\r
+        fis.close();\r
+        return new String(theData);\r
+    }\r
+\r
+    public static List<HttpTraffic> process(String httpSessionTraffic){\r
+        PayloadLogger pll = new PayloadLogger();\r
+        List<HttpTraffic> trafficList = pll.handleTcpDump(httpSessionTraffic);\r
+        return trafficList;\r
+    }\r
+\r
+    public static void main(String[]args) throws Exception {\r
+        String dump = readFile(".", args[0]);\r
+        PayloadLogger pll = new PayloadLogger();\r
+        List<HttpTraffic> trafficList = pll.handleTcpDump(dump);\r
+        reporter.finished(trafficList);\r
+        saveReport();\r
+    }\r
+\r
+    \r
+}
\ No newline at end of file
index 04f8f55c5f895aac3c7ed533740020203ebbecca..36fb95602c77c70076db159cdce4f16a07228122 100755 (executable)
 \r
 package org.collectionspace.services.IntegrationTests.xmlreplay;\r
 \r
+import org.apache.commons.httpclient.Header;\r
+\r
 import java.util.ArrayList;\r
+import java.util.HashMap;\r
 import java.util.List;\r
+import java.util.Map;\r
 \r
 /**\r
  * User: laramie\r
@@ -46,7 +50,36 @@ public class ServiceResult {
     public String error = "";\r
     public String fromTestID = "";\r
     public String auth = "";\r
+    public String boundary = "";\r
+    public String payloadStrictness = "";\r
+    public long contentLength = 0;\r
+    public String failureReason = "";\r
+    public Header[] responseHeaders = new Header[0];\r
     public List<Integer> expectedCodes = new ArrayList<Integer>();\r
+    private Map<String, TreeWalkResults> partSummaries = new HashMap<String, TreeWalkResults>();\r
+    public void addPartSummary(String label, TreeWalkResults list){\r
+        partSummaries.put(label, list);\r
+    }\r
+    public String partsSummary(boolean detailed){\r
+        StringBuffer buf = new StringBuffer();\r
+        if (!isDomWalkOK()){\r
+            if (detailed) buf.append("\r\nDOM CHECK FAILED:\r\n");\r
+            else buf.append("; DOM CHECK FAILED:");\r
+        }\r
+        for (Map.Entry<String,TreeWalkResults> entry : partSummaries.entrySet()) {\r
+            String key = entry.getKey();\r
+            TreeWalkResults value = entry.getValue();\r
+            buf.append(" label:"+key+": ");\r
+            if (detailed){\r
+                buf.append("\r\n");\r
+                buf.append(value.fullSummary());\r
+            } else {\r
+                buf.append(value.miniSummary());\r
+            }\r
+\r
+        }\r
+        return buf.toString();\r
+    }\r
     public boolean codeInSuccessRange(int code){\r
         if (0<=code && code<200){\r
             return false;\r
@@ -55,50 +88,113 @@ public class ServiceResult {
         }\r
         return true;\r
     }\r
+\r
+    public boolean isDomWalkOK(){\r
+        if (Tools.isEmpty(payloadStrictness)){\r
+            return true;\r
+        }\r
+        PAYLOAD_STRICTNESS strictness = PAYLOAD_STRICTNESS.valueOf(payloadStrictness);\r
+        for (Map.Entry<String,TreeWalkResults> entry : partSummaries.entrySet()) {\r
+            String key = entry.getKey();\r
+            TreeWalkResults value = entry.getValue();\r
+            if (value.hasDocErrors()){\r
+                failureReason = " : DOM DOC_ERROR; ";\r
+                return false;\r
+            }\r
+            switch (strictness){\r
+            case STRICT:\r
+                if (!value.isStrictMatch()) {\r
+                    failureReason = " : DOM NOT STRICT; ";\r
+                    return false;\r
+                }\r
+                break;\r
+            case ADDOK:\r
+                if (value.countFor(TreeWalkResults.TreeWalkEntry.STATUS.TEXT_DIFFERENT)>0) {\r
+                    failureReason = " : DOM TEXT_DIFFERENT; ";\r
+                    return false;\r
+                }\r
+                if (value.countFor(TreeWalkResults.TreeWalkEntry.STATUS.R_MISSING)>0){\r
+                    failureReason = " : DOM R_MISSING; ";\r
+                    return false;\r
+                }\r
+                break;\r
+            case TEXT:\r
+                if (value.countFor(TreeWalkResults.TreeWalkEntry.STATUS.TEXT_DIFFERENT)>0) {\r
+                    failureReason = " : DOM TEXT_DIFFERENT; ";\r
+                    return false;\r
+                }\r
+                break;\r
+            case TREE:\r
+                if (!value.treesMatch()) {\r
+                    failureReason = " : DOM TREE MISMATCH; ";\r
+                    return false;\r
+                }\r
+                break;\r
+            case ZERO:\r
+                break;\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
     public boolean gotExpectedResult(){\r
+        if (Tools.notEmpty(failureReason)){\r
+            return false;\r
+        }\r
         for (Integer oneExpected : expectedCodes){\r
             if (responseCode == oneExpected){\r
-                return true;\r
+                return isDomWalkOK();\r
             }\r
         }\r
-        if (expectedCodes.size()>0 && codeInSuccessRange(responseCode)){ //none found, but result expected.\r
+        if ( expectedCodes.size()>0 && codeInSuccessRange(responseCode)){ //none found, but result expected.\r
             for (Integer oneExpected : expectedCodes){\r
                 if ( ! codeInSuccessRange(oneExpected)){\r
-                    return false;\r
+                    return isDomWalkOK();\r
                 }\r
             }\r
         }\r
-        return codeInSuccessRange(responseCode);\r
+        boolean ok = codeInSuccessRange(responseCode);\r
+        if (ok) {\r
+            return isDomWalkOK();\r
+        }\r
+        failureReason = " : STATUS CODE UNEXPECTED; ";\r
+        return false;\r
     }\r
+\r
     //public static final String[] DUMP_OPTIONS = {"minimal", "detailed", "full"};\r
     public static enum DUMP_OPTIONS {minimal, detailed, full};\r
 \r
+    public static enum PAYLOAD_STRICTNESS {ZERO, ADDOK, TREE, TEXT, STRICT};\r
+\r
     public String toString(){\r
         return detail(true);\r
 \r
     }\r
     public String detail(boolean includePayloads){\r
-        return "{ServiceResult: "\r
-                + ( Tools.notEmpty(testID) ? " testID:"+testID : "" )\r
-                + ( Tools.notEmpty(testGroupID) ? "; testGroupID:"+testGroupID : "" )\r
-                + ( Tools.notEmpty(fromTestID) ? "; fromTestID:"+fromTestID : "" )\r
+        return "{"\r
+                + ( gotExpectedResult() ? "SUCCESS" : "FAILURE"  )\r
+                + failureReason\r
                 +"; "+method\r
                 +"; "+responseCode\r
+                + ( (expectedCodes.size()>0) ? "; expectedCodes:"+expectedCodes : "" )\r
+                + ( Tools.notEmpty(testID) ? "; testID:"+testID : "" )\r
+                + ( Tools.notEmpty(testGroupID) ? "; testGroupID:"+testGroupID : "" )\r
+                + ( Tools.notEmpty(fromTestID) ? "; fromTestID:"+fromTestID : "" )\r
                 + ( Tools.notEmpty(responseMessage) ? "; msg:"+responseMessage : "" )\r
                 +"; URL:"+fullURL\r
                 +"; auth: "+auth\r
                 + ( Tools.notEmpty(deleteURL) ? "; deleteURL:"+deleteURL : "" )\r
                 + ( Tools.notEmpty(location) ? "; location.CSID:"+location : "" )\r
                 + ( Tools.notEmpty(error) ? "; ERROR:"+error : "" )\r
-                + ( (expectedCodes.size()>0) ? "; expectedCodes:"+expectedCodes : "" )\r
                 + "; gotExpected:"+gotExpectedResult()\r
                 + ( includePayloads && Tools.notEmpty(result) ? "; result:"+result : "" )\r
+                + ( partsSummary(true))\r
                 +"}";\r
     }\r
     public String minimal(){\r
         return "{"\r
                 + ( gotExpectedResult() ? "SUCCESS" : "FAILURE"  )\r
-\r
+                + failureReason\r
                 + ( Tools.notEmpty(testID) ? "; "+testID : "" )\r
                 +"; "+method\r
                 +"; "+responseCode\r
@@ -107,6 +203,7 @@ public class ServiceResult {
                 +"; URL:"+fullURL\r
                 +"; auth: "+auth\r
                 + ( Tools.notEmpty(error) ? "; ERROR:"+error : "" )\r
+                + ( partsSummary(false))\r
                 +"}";\r
     }\r
     public String dump(ServiceResult.DUMP_OPTIONS opt){\r
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
new file mode 100755 (executable)
index 0000000..3013031
--- /dev/null
@@ -0,0 +1,157 @@
+/**\r
+ * This document is a part of the source code and related artifacts\r
+ * for CollectionSpace, an open source collections management system\r
+ * for museums and related institutions:\r
+ *\r
+ * http://www.collectionspace.org\r
+ * http://wiki.collectionspace.org\r
+ *\r
+ * Copyright (c) 2009 Regents of the University of California\r
+ *\r
+ * Licensed under the Educational Community License (ECL), Version 2.0.\r
+ * You may not use this file except in compliance with this License.\r
+ *\r
+ * You may obtain a copy of the ECL 2.0 License at\r
+ * https://source.collectionspace.org/collection-space/LICENSE.txt\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ */\r
+\r
+package org.collectionspace.services.IntegrationTests.xmlreplay;\r
+\r
+import java.util.ArrayList;\r
+\r
+/**\r
+ * User: laramie\r
+ * $LastChangedRevision:  $\r
+ * $LastChangedDate:  $\r
+ */\r
+public class TreeWalkResults extends ArrayList<TreeWalkResults.TreeWalkEntry> {\r
+\r
+    public static class TreeWalkEntry {\r
+        public String lpath = "";\r
+        public String rpath = "";\r
+        public String ltextTrimmed = "";\r
+        public String rtextTrimmed = "";\r
+        public String message = "";\r
+        public String errmessage = "";\r
+        public static enum STATUS {INFO, MATCHED, R_MISSING, R_ADDED, DOC_ERROR, TEXT_DIFFERENT};\r
+        public STATUS status;\r
+        public String toString(){\r
+            return\r
+                 "{"\r
+                 +status.name()\r
+                 +(Tools.notEmpty(lpath) ? ", L.path:"+lpath : "")\r
+                 +(Tools.notEmpty(rpath) ? ", R.path:"+rpath : "")\r
+                 +(Tools.notEmpty(message) ? ", message:"+message : "")\r
+                 +((status != STATUS.MATCHED) && Tools.notEmpty(ltextTrimmed) ? ",\r\n    L.trimmed:"+ltextTrimmed : "")\r
+                 +((status != STATUS.MATCHED) && Tools.notEmpty(rtextTrimmed) ? ",\r\n    R.trimmed:"+rtextTrimmed : "")\r
+                 +"}";\r
+\r
+        }\r
+    }\r
+\r
+    public boolean hasDocErrors(){\r
+        for (TreeWalkEntry entry : this){\r
+            if (entry.status == TreeWalkEntry.STATUS.DOC_ERROR){\r
+                return true;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
+    public String getErrorMessages(){\r
+        StringBuffer buf = new StringBuffer();\r
+        boolean first = true;\r
+        for (TreeWalkEntry entry : this){\r
+            if ( Tools.notEmpty(entry.errmessage)){\r
+                if (first) {\r
+                    buf.append(",errors:");\r
+                } else {\r
+                    buf.append(',');\r
+                }\r
+                buf.append('\''+entry.errmessage+"\'");\r
+                first = false;\r
+            }\r
+        }\r
+        return buf.toString();\r
+    }\r
+\r
+\r
+\r
+    public boolean isStrictMatch(){\r
+        for (TreeWalkEntry entry : this){\r
+            if (entry.status == TreeWalkEntry.STATUS.DOC_ERROR){\r
+                return false;\r
+            }\r
+            if ( !(   entry.status == TreeWalkEntry.STATUS.MATCHED\r
+                   || entry.status == TreeWalkEntry.STATUS.INFO)){\r
+                return false;\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+    public int getMismatchCount(){\r
+        int c = 0;\r
+        for (TreeWalkEntry entry : this){\r
+            if ( entry.status == TreeWalkEntry.STATUS.DOC_ERROR\r
+                || entry.status != TreeWalkEntry.STATUS.MATCHED\r
+                || entry.status != TreeWalkEntry.STATUS.INFO){\r
+                c++;\r
+            }\r
+        }\r
+        return c;\r
+    }\r
+    /** For our purposes, trees match if they have the same element tree structure - no checking is done for text node changes. */\r
+    public boolean treesMatch(){\r
+        for (TreeWalkEntry entry : this){\r
+            if (entry.status == TreeWalkEntry.STATUS.DOC_ERROR\r
+                || entry.status == TreeWalkEntry.STATUS.R_MISSING\r
+                || entry.status == TreeWalkEntry.STATUS.R_ADDED  ){\r
+                return false;\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
+    public int countFor(TreeWalkEntry.STATUS status){\r
+        int count = 0;\r
+        for (TreeWalkEntry entry : this){\r
+            if (entry.status.equals(status)){\r
+                count++;\r
+            }\r
+        }\r
+        return count;\r
+    }\r
+\r
+    public String miniSummary(){\r
+        //MATCHED, INFO, R_MISSING, R_ADDED, TEXT_DIFFERENT};\r
+        StringBuffer buf = new StringBuffer();\r
+        buf.append("{");\r
+        boolean nextline = false;\r
+        for (TreeWalkEntry.STATUS st : TreeWalkEntry.STATUS.values()){\r
+            if (nextline) buf.append(',');\r
+            buf.append(st.name()+':'+countFor(st));\r
+            nextline = true;\r
+        }\r
+        buf.append(getErrorMessages());\r
+        buf.append("}");\r
+        return buf.toString();\r
+    }\r
+\r
+    public String fullSummary(){\r
+        StringBuffer buf = new StringBuffer();\r
+        for (TreeWalkResults.TreeWalkEntry entry : this){\r
+            buf.append(entry.toString()).append("\r\n");\r
+        }\r
+        return buf.toString();\r
+    }\r
+\r
+\r
+    public String leftID;\r
+    public String rightID;\r
+}
\ No newline at end of file
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
new file mode 100755 (executable)
index 0000000..18d5106
--- /dev/null
@@ -0,0 +1,184 @@
+/**\r
+ * This document is a part of the source code and related artifacts\r
+ * for CollectionSpace, an open source collections management system\r
+ * for museums and related institutions:\r
+ *\r
+ * http://www.collectionspace.org\r
+ * http://wiki.collectionspace.org\r
+ *\r
+ * Copyright (c) 2009 Regents of the University of California\r
+ *\r
+ * Licensed under the Educational Community License (ECL), Version 2.0.\r
+ * You may not use this file except in compliance with this License.\r
+ *\r
+ * You may obtain a copy of the ECL 2.0 License at\r
+ * https://source.collectionspace.org/collection-space/LICENSE.txt\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ */\r
+package org.collectionspace.services.IntegrationTests.xmlreplay;\r
+\r
+import org.jdom.Document;\r
+import org.jdom.Element;\r
+import org.jdom.JDOMException;\r
+import org.jdom.input.SAXBuilder;\r
+import org.jaxen.XPath;\r
+import org.jaxen.jdom.JDOMXPath;\r
+\r
+\r
+import java.io.IOException;\r
+import java.io.StringReader;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.collectionspace.services.IntegrationTests.xmlreplay.TreeWalkResults.TreeWalkEntry;\r
+\r
+/**\r
+ * User: laramie\r
+ * $LastChangedRevision:  $\r
+ * $LastChangedDate:  $\r
+ */\r
+public class XmlCompareJdom {\r
+\r
+private static final String DEFAULT_SAX_DRIVER_CLASS = "org.apache.xerces.parsers.SAXParser";\r
+\r
+    public static org.jdom.Document getDocumentFromContent(String source) throws IOException, JDOMException {\r
+        org.jdom.Document doc;\r
+        SAXBuilder builder;\r
+        builder = new SAXBuilder();\r
+        builder.setValidation(false); //has no effect, I think.\r
+        doc = builder.build(new StringReader(source));\r
+        return doc;\r
+    }\r
+\r
+    public static TreeWalkResults compareParts(String expectedContent, String leftID, String actualPartContent, String rightID){\r
+        TreeWalkResults list = new TreeWalkResults();\r
+        try {\r
+\r
+            list.leftID = leftID;\r
+            list.rightID = rightID;\r
+            TreeWalkResults.TreeWalkEntry infoentry = new TreeWalkResults.TreeWalkEntry();\r
+            infoentry.status = TreeWalkResults.TreeWalkEntry.STATUS.INFO;\r
+            infoentry.message = "\r\n    LEFT file: "+leftID+"\r\n    RIGHT file: "+rightID;\r
+            list.add(infoentry);\r
+            if (Tools.isEmpty(expectedContent)){\r
+                TreeWalkEntry entry = new TreeWalkEntry();\r
+                entry.status = TreeWalkEntry.STATUS.DOC_ERROR;\r
+                entry.errmessage = "L dom was empty.";\r
+                list.add(entry);\r
+            } else if (Tools.isEmpty(actualPartContent)){\r
+                TreeWalkEntry entry = new TreeWalkEntry();\r
+                entry.errmessage = "R dom was empty.";\r
+                entry.status = TreeWalkEntry.STATUS.DOC_ERROR;\r
+                list.add(entry);\r
+            } else {\r
+                Document expected = getDocumentFromContent(expectedContent);\r
+                Document actual = getDocumentFromContent(actualPartContent);\r
+                treeWalk(expected, actual, list);\r
+            }\r
+        } catch (Throwable t){\r
+            String msg = "ERROR in XmlReplay.compareParts(): "+t;\r
+            System.out.println(msg);\r
+            TreeWalkEntry entry = new TreeWalkEntry();\r
+                entry.status = TreeWalkEntry.STATUS.DOC_ERROR;\r
+                entry.errmessage = msg;\r
+                list.add(entry);\r
+        }\r
+        return list;\r
+    }\r
+\r
+    public static List select(Element element, String xpathExpression) throws Exception {\r
+        XPath xpath = new JDOMXPath(xpathExpression);\r
+        return xpath.selectNodes(element);\r
+    }\r
+\r
+    public static Object selectSingleNode(Element element, String xpathExpression) throws Exception {\r
+        XPath xpath = new JDOMXPath(xpathExpression);\r
+        return xpath.selectSingleNode(element);\r
+    }\r
+\r
+\r
+\r
+\r
+    public static boolean treeWalk(Document left, Document right, TreeWalkResults list) throws Exception {\r
+        boolean res = treeWalk(left.getRootElement(), right.getRootElement(), "/", list);\r
+        return res;\r
+    }\r
+\r
+    public static boolean treeWalk(Element left, Element right, String parentPath, TreeWalkResults msgList) throws Exception {\r
+        String SPACE = "     ";\r
+        if (left == null && right == null){\r
+            return true;\r
+        }\r
+        if (left == null){\r
+            return false;\r
+        }\r
+        if (right == null){\r
+            return false;\r
+        }\r
+        List l = left.getChildren();\r
+        Map foundRightMap = new HashMap();\r
+        boolean result = true;\r
+        for (Object o : l) {\r
+            if (!(o instanceof Element)){\r
+                continue;\r
+            }\r
+            Element leftChild = (Element)o;\r
+            String leftChildName = leftChild.getName();\r
+            if (Tools.isEmpty(leftChildName)){\r
+                continue;\r
+            }\r
+            String leftChildPath = Tools.glue(parentPath, "/", leftChildName);\r
+            Element rightChild  = (Element)selectSingleNode(right,leftChildName);\r
+            if (rightChild == null){\r
+                TreeWalkEntry entry = new TreeWalkEntry();\r
+                entry.lpath = leftChildPath;\r
+                entry.status = TreeWalkEntry.STATUS.R_MISSING;\r
+                msgList.add(entry);\r
+                continue;\r
+            }\r
+            foundRightMap.put(leftChildName, "OK");\r
+            String leftChildTextTrim = leftChild.getText().trim();\r
+            String rightChildTextTrim = rightChild.getText().trim();\r
+            TreeWalkEntry entry = new TreeWalkEntry();\r
+            entry.ltextTrimmed = leftChildTextTrim;\r
+            entry.rtextTrimmed = rightChildTextTrim;\r
+            entry.lpath = leftChildPath;\r
+            entry.rpath = leftChildPath; //same\r
+\r
+            if (leftChildTextTrim.equals(rightChildTextTrim)){\r
+                entry.status = TreeWalkEntry.STATUS.MATCHED;\r
+                msgList.add(entry);\r
+            } else {\r
+                entry.status = TreeWalkEntry.STATUS.TEXT_DIFFERENT;\r
+                msgList.add(entry);\r
+            }\r
+\r
+            //============ DIVE !! =====================================================\r
+            result = result && treeWalk( leftChild, rightChild, leftChildPath, msgList);\r
+        }\r
+        for (Object r : right.getChildren()){\r
+            if (!(r instanceof Element)){\r
+                continue;\r
+            }\r
+            Element rightChild = (Element)r;\r
+            String rname = rightChild.getName();\r
+            if (null==foundRightMap.get(rname)){\r
+                String rightChildPath = Tools.glue(parentPath, "/", rname);\r
+\r
+                TreeWalkEntry entry = new TreeWalkEntry();\r
+                entry.rpath = rightChildPath;\r
+                entry.status = TreeWalkEntry.STATUS.R_ADDED;\r
+                msgList.add(entry);\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+    \r
+}\r
index 33f996b64c4aebe8348047dcd71a2551aa0ad091..4bd05f791c73033ebb2a53fe8e5b5eabec57aab2 100755 (executable)
@@ -2,13 +2,19 @@ package org.collectionspace.services.IntegrationTests.xmlreplay;
 \r
 import org.apache.commons.cli.*;\r
 \r
+import org.apache.commons.io.FileUtils;\r
 import org.apache.commons.jexl2.JexlContext;\r
 import org.apache.commons.jexl2.JexlEngine;\r
 import org.apache.commons.jexl2.MapContext;\r
-import org.dom4j.Document;\r
-import org.dom4j.DocumentException;\r
-import org.dom4j.Node;\r
+import org.dom4j.*;\r
 import org.dom4j.io.SAXReader;\r
+import org.jdom.input.SAXBuilder;\r
+import org.xml.sax.InputSource;\r
+\r
+\r
+import org.jdom.Document;\r
+import org.jdom.Element;\r
+import org.jdom.JDOMException;\r
 \r
 import java.io.*;\r
 import java.util.*;\r
@@ -88,8 +94,8 @@ public class XmlReplay {
 \r
     // ============== METHODS ===========================================================\r
 \r
-    public Document openMasterConfigFile(String masterFilename) throws FileNotFoundException {\r
-        Document document = getDocument(Tools.glue(basedir, "/", masterFilename)); //will check full path first, then checks relative to PWD.\r
+    public org.dom4j.Document openMasterConfigFile(String masterFilename) throws FileNotFoundException {\r
+        org.dom4j.Document document = getDocument(Tools.glue(basedir, "/", masterFilename)); //will check full path first, then checks relative to PWD.\r
         if (document == null){\r
             throw new FileNotFoundException("XmlReplay master control file ("+masterFilename+") not found in basedir: "+basedir+". Exiting test.");\r
         }\r
@@ -99,8 +105,8 @@ public class XmlReplay {
     /** specify the master config file, relative to getBaseDir(), but ignore any tests or testGroups in the master.\r
      *  @return a Document object, which you don't need to use: all options will be stored in XmlReplay instance.\r
      */\r
-    public Document readOptionsFromMasterConfigFile(String masterFilename) throws FileNotFoundException {\r
-        Document document = openMasterConfigFile(masterFilename);\r
+    public org.dom4j.Document readOptionsFromMasterConfigFile(String masterFilename) throws FileNotFoundException {\r
+        org.dom4j.Document document = openMasterConfigFile(masterFilename);\r
         protoHostPort = document.selectSingleNode("/xmlReplayMaster/protoHostPort").getText().trim();\r
         AuthsMap authsMap = readAuths(document);\r
         setDefaultAuthsMap(authsMap);\r
@@ -117,7 +123,7 @@ public class XmlReplay {
      *  and setting defaults from this instance, but not sharing ServiceResult objects or maps. */\r
     public List<List<ServiceResult>> runMaster(String masterFilename, boolean readOptionsFromMaster) throws Exception {\r
         List<List<ServiceResult>> list = new ArrayList<List<ServiceResult>>();\r
-        Document document;\r
+        org.dom4j.Document document;\r
         if (readOptionsFromMaster){\r
             document = readOptionsFromMasterConfigFile(masterFilename);\r
         } else {\r
@@ -225,7 +231,7 @@ public class XmlReplay {
         }\r
     }\r
 \r
-    public static AuthsMap readAuths(Document document){\r
+    public static AuthsMap readAuths(org.dom4j.Document document){\r
     Map<String, String> map = new HashMap<String, String>();\r
         List<Node> authNodes = document.selectNodes("//auths/auth");\r
         for (Node auth : authNodes) {\r
@@ -255,7 +261,7 @@ public class XmlReplay {
         return new Dump();\r
     }\r
 \r
-    public static Dump readDumpOptions(Document document){\r
+    public static Dump readDumpOptions(org.dom4j.Document document){\r
         Dump dump = getDumpConfig();\r
         Node dumpNode = document.selectSingleNode("//dump");\r
         if (dumpNode != null){\r
@@ -284,7 +290,8 @@ public class XmlReplay {
             } else {\r
                 result.bDoingSinglePartPayload = false;\r
                 List<Node> parts = testNode.selectNodes("parts/part");\r
-                if (parts == null || parts.size()==0){  //path is just /testGroup/test/part/\r
+                if (parts == null || parts.size()==0){\r
+                    //path is just /testGroup/test/part/\r
                     String commonPartName = testNode.valueOf("part/label");\r
                     String testfile = testNode.valueOf("part/filename");\r
                     String fullTestFilename = xmlReplayBaseDir + '/' + testfile;\r
@@ -293,7 +300,8 @@ public class XmlReplay {
                     }\r
                     result.partsList.add(commonPartName);\r
                     result.filesList.add(fullTestFilename);\r
-                } else { // path is /testGroup/test/parts/part/\r
+                } else {\r
+                    // path is /testGroup/test/parts/part/\r
                     for (Node part : parts){\r
                         String commonPartName = part.valueOf("label");\r
                         String filename = part.valueOf("filename");\r
@@ -342,9 +350,8 @@ public class XmlReplay {
         return result;\r
     }\r
 \r
-\r
     public static org.dom4j.Document getDocument(String xmlFileName) {\r
-        Document document = null;\r
+        org.dom4j.Document document = null;\r
         SAXReader reader = new SAXReader();\r
         try {\r
             document = reader.read(xmlFileName);\r
@@ -355,6 +362,57 @@ public class XmlReplay {
         return document;\r
     }\r
 \r
+    protected static String validateResponse(ServiceResult serviceResult,\r
+                                             Map<String, ServiceResult> serviceResultsMap,\r
+                                             PartsStruct expectedResponseParts){\r
+        String OK = "";\r
+        if (expectedResponseParts == null) return OK;\r
+        if (serviceResult == null) return OK;\r
+        if (serviceResult.result.length() == 0) return OK;\r
+        String responseDump = serviceResult.result;\r
+        //System.out.println("responseDump: "+responseDump);\r
+        PayloadLogger.HttpTraffic traffic = PayloadLogger.readPayloads(responseDump, serviceResult.boundary, serviceResult.contentLength);\r
+        try {\r
+            for (int i=0; i<expectedResponseParts.partsList.size(); i++){\r
+                String fileName = expectedResponseParts.filesList.get(i);\r
+                String label = expectedResponseParts.partsList.get(i);\r
+                byte[] b = FileUtils.readFileToByteArray(new File(fileName));\r
+                String expectedPartContent = new String(b);\r
+                System.out.println("expected: "+label+ " content ==>\r\n"+expectedPartContent);\r
+                PayloadLogger.Part partFromServer = traffic.getPart(label);\r
+                String partFromServerContent = "";\r
+                if (partFromServer != null){\r
+                    partFromServerContent = partFromServer.getContent();\r
+                } else {\r
+                    partFromServerContent = "";\r
+                }\r
+                //if (partFromServer!=null) {\r
+                    //System.out.println("====part content from server.   label-->"+label+"<-- \r\npart-->"+partFromServerContent+"<--");\r
+\r
+                    String leftID  = "{from expected part, label:"+label+" filename: "+fileName+"}";\r
+                    String rightID = "{from server, label:"+label\r
+                                        //+" testGroupID: "+serviceResult.testGroupID\r
+                                        +" fromTestID: "+serviceResult.fromTestID\r
+                                        +" URL: "+serviceResult.fullURL\r
+                                        +"}";\r
+                    TreeWalkResults list =\r
+                        XmlCompareJdom.compareParts(expectedPartContent,\r
+                                                    leftID,\r
+                                                    partFromServerContent,\r
+                                                    rightID);\r
+                    //if (list.getMismatchCount()>0){\r
+                        serviceResult.addPartSummary(label, list);\r
+                    //}\r
+                //}\r
+            }\r
+        } catch (Exception e){\r
+            String err = "ERROR in XmlReplay.validateResponse() : "+e; \r
+            //System.out.println(err);\r
+            return err  ;\r
+        }\r
+        return OK;\r
+    }\r
+\r
 \r
     //================= runXmlReplayFile ======================================================\r
 \r
@@ -374,7 +432,7 @@ public class XmlReplay {
         List<ServiceResult> results = new ArrayList<ServiceResult>();\r
 \r
         String controlFile = Tools.glue(xmlReplayBaseDir, "/", controlFileName);\r
-        Document document;\r
+        org.dom4j.Document document;\r
         document = getDocument(controlFile); //will check full path first, then checks relative to PWD.\r
         if (document==null){\r
             throw new FileNotFoundException("XmlReplay control file ("+controlFileName+") not found in basedir: "+xmlReplayBaseDir+" Exiting test.");\r
@@ -468,6 +526,13 @@ public class XmlReplay {
                          }\r
                     }\r
 \r
+                    Node responseNode = testNode.selectSingleNode("response");\r
+                    PartsStruct expectedResponseParts = null;\r
+                    if (responseNode!=null){\r
+                        expectedResponseParts = PartsStruct.readParts(responseNode, testID, xmlReplayBaseDir);\r
+                        //System.out.println("reponse parts: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+expectedResponseParts);\r
+                    }\r
+\r
                     ServiceResult serviceResult;\r
                     boolean isPOST = method.equalsIgnoreCase("POST");\r
                     boolean isPUT =  method.equalsIgnoreCase("PUT");\r
@@ -498,8 +563,11 @@ public class XmlReplay {
                         if (pr!=null){\r
                             serviceResult = XmlReplayTransport.doDELETE(pr.deleteURL, authForTest, testIDLabel, fromTestID);\r
                             serviceResult.fromTestID = fromTestID;\r
+                            if (expectedCodes.size()>0){\r
+                                serviceResult.expectedCodes = expectedCodes;\r
+                            }\r
                             results.add(serviceResult);\r
-                            if (serviceResult.gotExpectedResult()){\r
+                            if (serviceResult.gotExpectedResult()){  //gotExpectedResult depends on serviceResult.expectedCodes.\r
                                 serviceResultsMap.remove(fromTestID);\r
                             }\r
                         } else {\r
@@ -537,6 +605,18 @@ public class XmlReplay {
                     if (Tools.isEmpty(serviceResult.testID)) serviceResult.testID = testIDLabel;\r
                     if (Tools.isEmpty(serviceResult.testGroupID)) serviceResult.testGroupID = testGroupID;\r
 \r
+                    Node expectedLevel = testNode.selectSingleNode("response/expected");\r
+                    if (expectedLevel!=null){\r
+                        String level = expectedLevel.valueOf("@level");\r
+                        serviceResult.payloadStrictness = level;\r
+                    }\r
+\r
+                    String vError = validateResponse(serviceResult, serviceResultsMap, expectedResponseParts);\r
+                    if (Tools.notEmpty(vError)){\r
+                        serviceResult.error = vError;\r
+                        serviceResult.failureReason = " : VALIDATION ERROR; ";\r
+                    }\r
+\r
                     String serviceResultRow = serviceResult.dump(dump.dumpServiceResult);\r
                     String leader = (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.detailed) ? "XmlReplay:"+testIDLabel+": ": "";\r
                     System.out.println(leader+serviceResultRow+"\r\n");\r
index f05ab135b4ad0deb11015cbad3d4bd33dea52d40..f0b12b5c6f4a8fcdad28ebbf78480359c63568b0 100755 (executable)
@@ -132,7 +132,6 @@ public class XmlReplayTest {
                     buff.append(ROWSTARTRED+serviceResult.minimal()+ROWENDRED);\r
                 }\r
             }\r
-\r
         }\r
         buff.append(TBLEND);\r
         summary.table = buff.toString();\r
index b86578775bab28cd5f772aef201282fac3f4286b..3592d11cbb241993aa770d24556c8dcb6aa24e7c 100755 (executable)
@@ -23,6 +23,7 @@
 \r
 package org.collectionspace.services.IntegrationTests.xmlreplay;\r
 \r
+import org.apache.commons.httpclient.Header;\r
 import org.apache.commons.httpclient.HttpClient;\r
 import org.apache.commons.httpclient.methods.DeleteMethod;\r
 import org.apache.commons.httpclient.methods.GetMethod;\r
@@ -34,6 +35,7 @@ import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;\r
 import java.net.HttpURLConnection;\r
 import java.net.URL;\r
+import java.util.Arrays;\r
 import java.util.List;\r
 import java.util.Map;\r
 \r
@@ -59,10 +61,19 @@ public class XmlReplayTransport {
 \r
         int statusCode1 = client.executeMethod(getMethod);\r
         pr.responseCode = statusCode1;\r
+        pr.fromTestID = fromTestID;\r
         pr.method = "GET";\r
         try {\r
             pr.result = getMethod.getResponseBodyAsString();\r
             pr.responseMessage = getMethod.getStatusText();\r
+            Header[] headers = getMethod.getResponseHeaders();\r
+            pr.responseHeaders = Arrays.copyOf(headers, headers.length);\r
+            Header hdr = getMethod.getResponseHeader("CONTENT-TYPE");\r
+            if (hdr!=null){\r
+                String hdrStr = hdr.toExternalForm();\r
+                pr.boundary = PayloadLogger.parseBoundary(hdrStr);\r
+            }\r
+            pr.contentLength = getMethod.getResponseContentLength();\r
         } catch (Throwable t){\r
             //System.err.println("ERROR getting content from response: "+t);\r
             pr.error = t.toString();\r
@@ -77,6 +88,7 @@ public class XmlReplayTransport {
         ServiceResult pr = new ServiceResult();\r
         pr.method = "DELETE";\r
         pr.fullURL = urlString;\r
+        pr.fromTestID = fromTestID;\r
         if (Tools.isEmpty(urlString)){\r
             pr.error = "url was empty.  Check the result for fromTestID: "+fromTestID+". currentTest: "+testID;\r
             return pr;\r
@@ -207,6 +219,8 @@ public class XmlReplayTransport {
             }\r
             String msg = sb.toString();\r
             result.result = msg;\r
+            result.boundary = PayloadLogger.parseBoundary(conn.getHeaderField("CONTENT-TYPE"));\r
+\r
             rd.close();\r
         } catch (Throwable t){\r
             //System.err.println("ERROR getting content from response: "+t);\r
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
new file mode 100755 (executable)
index 0000000..c993e79
--- /dev/null
@@ -0,0 +1,195 @@
+/**\r
+ * This document is a part of the source code and related artifacts\r
+ * for CollectionSpace, an open source collections management system\r
+ * for museums and related institutions:\r
+ *\r
+ * http://www.collectionspace.org\r
+ * http://wiki.collectionspace.org\r
+ *\r
+ * Copyright (c) 2009 Regents of the University of California\r
+ *\r
+ * Licensed under the Educational Community License (ECL), Version 2.0.\r
+ * You may not use this file except in compliance with this License.\r
+ *\r
+ * You may obtain a copy of the ECL 2.0 License at\r
+ * https://source.collectionspace.org/collection-space/LICENSE.txt\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ */\r
+package org.collectionspace.services.IntegrationTests.test;\r
+\r
+import org.collectionspace.services.IntegrationTests.xmlreplay.TreeWalkResults;\r
+import org.collectionspace.services.IntegrationTests.xmlreplay.XmlCompareJdom;\r
+import org.testng.Assert;\r
+import org.testng.annotations.Test;\r
+\r
+/**\r
+ * User: laramie\r
+ * $LastChangedRevision:  $\r
+ * $LastChangedDate:  $\r
+ */\r
+public class XmlCompareJdomTest {\r
+\r
+\r
+    private void testBanner(String msg){\r
+        String BANNER ="-------------------------------------------------------";\r
+        System.out.println(BANNER+"\r\n"+this.getClass().getName()+"\r\n"+msg+"\r\n"+BANNER);\r
+    }\r
+    private void printTreeWalkResults(TreeWalkResults list){\r
+        for (TreeWalkResults.TreeWalkEntry entry : list){\r
+            System.out.println(entry.toString());\r
+        }\r
+    }\r
+\r
+    private void assertTreeWalkResults(TreeWalkResults results,\r
+                                       int addedRight,\r
+                                       int missingRight,\r
+                                       int textMismatches,\r
+                                       boolean strictMatch,\r
+                                       boolean treesMatch){\r
+        System.out.println("assertTreeWalkResults: ");\r
+\r
+        int addedr = results.countFor(TreeWalkResults.TreeWalkEntry.STATUS.R_ADDED);\r
+        int missingr = results.countFor(TreeWalkResults.TreeWalkEntry.STATUS.R_MISSING);\r
+        int tdiff = results.countFor(TreeWalkResults.TreeWalkEntry.STATUS.TEXT_DIFFERENT);\r
+        int badCount = results.getMismatchCount();\r
+        boolean strict = results.isStrictMatch();\r
+        boolean treeOK = results.treesMatch();\r
+\r
+        String expected = "    expected: addedRight:"+addedRight+",missingRight:"+missingRight+",textMismatches:"+textMismatches\r
+                              +",strictMatch:"+strictMatch+",treesMatch:"+treesMatch;\r
+\r
+        String actual   = "    actual:   addedRight:"+addedr+",missingRight:"+missingr+",textMismatches:"+tdiff\r
+                              +",strictMatch:"+strict+",treesMatch:"+treeOK;\r
+\r
+        String exp_act = expected +"\r\n"+actual+"\r\n";\r
+        System.out.print(exp_act);\r
+\r
+        printTreeWalkResults(results);\r
+\r
+\r
+        boolean done = false;\r
+        try {\r
+            Assert.assertEquals(addedr, addedRight, "assertTreeWalkResults:R_ADDED mismatch."+exp_act);\r
+\r
+            Assert.assertEquals(missingr, missingRight, "assertTreeWalkResults:R_MISSING mismatch."+exp_act);\r
+\r
+            Assert.assertEquals(tdiff, textMismatches, "assertTreeWalkResults:TEXT_DIFFERENT mismatch."+exp_act);\r
+\r
+\r
+            Assert.assertTrue((strict==strictMatch), "assertTreeWalkResults:strictMatch mismatch."+exp_act);\r
+\r
+            Assert.assertTrue((treeOK==treesMatch), "assertTreeWalkResults:treesMatch mismatch."+exp_act);\r
+\r
+            System.out.println("SUCCESS: assertTreeWalkResults done.\r\n");\r
+            done = true;\r
+        } finally {\r
+            if (!done) System.out.println("FAILURE: assertTreeWalkResults failed an assertion. See surefire report.\r\n");\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testXmlCompareJdom(){\r
+        testBanner("testXmlCompareJdom");\r
+        TreeWalkResults results =\r
+                    XmlCompareJdom.compareParts(expectedPartContent,\r
+                                        "expected",\r
+                                        partFromServer,\r
+                                        "from-server");\r
+        assertTreeWalkResults(results,0,0,0,true,true);\r
+                                   // addedRight,missingRight,textMismatches,strictMatch,treesMatch\r
+    }\r
+\r
+    @Test\r
+    public void testTextContentDifferent(){\r
+        testBanner("testTextContentDifferent");\r
+        TreeWalkResults results =\r
+            XmlCompareJdom.compareParts(expectedPartContent,\r
+                                        "expected",\r
+                                        srvHEAD+srvEN2+srvDEPOSITOR+srvFOOT,\r
+                                        "from-server");\r
+        assertTreeWalkResults(results,0,0,1,false,true);\r
+                                   // addedRight,missingRight,textMismatches,strictMatch,treesMatch\r
+    }\r
+\r
+\r
+    @Test\r
+    public void testAddedR(){\r
+        testBanner("testAddedR");\r
+        TreeWalkResults results =\r
+            XmlCompareJdom.compareParts(expectedPartContent,\r
+                                        "expected",\r
+                                        srvHEAD+srvEN+exNEWTREE+srvDEPOSITOR+exNEW+srvFOOT,\r
+                                        "from-server");\r
+        assertTreeWalkResults(results,2,0,0,false,false);\r
+                                   // addedRight,missingRight,textMismatches,strictMatch,treesMatch\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testAddedL(){\r
+        testBanner("testAddedL");\r
+        TreeWalkResults results =\r
+            XmlCompareJdom.compareParts(exHEAD + exEN_WCH + exNEWTREE + exDEP  + exNEW + exFOOT,\r
+                                    "expected",\r
+                                    partFromServer,\r
+                                    "from-server");\r
+        assertTreeWalkResults(results,0,3,0,false,false);\r
+                                   // addedRight,missingRight,textMismatches,strictMatch,treesMatch\r
+    }\r
+\r
+    @Test\r
+    public void testChildrenReordered(){\r
+        testBanner("testChildrenReordered");\r
+        TreeWalkResults results =\r
+            XmlCompareJdom.compareParts(exHEAD  + exDEP + exEN + exFOOT,\r
+                                    "expected",\r
+                                    partFromServer,\r
+                                    "from-server");\r
+        assertTreeWalkResults(results,0,0,0,true,true);\r
+                                   // addedRight,missingRight,textMismatches,strictMatch,treesMatch\r
+    }\r
+\r
+\r
+    // ============  expected part, will be used as LEFT tree ==========================================================\r
+    private static String exHEAD    ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"\r
+                                    +"<ns2:objectexit_common \r\n"\r
+                                    +"    xmlns:ns2=\"http://collectionspace.org/services/objectexit\" \r\n"\r
+                                    +"    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \r\n"\r
+                                    +"    xsi:schemaLocation=\"http://collectionspace.org/services/objectexit http://services.collectionspace.org/objectexit/objectexit_common.xsd\">\r\n";\r
+    private static String exEN      =" <exitNumber>objectexitNumber-1290026472360</exitNumber>\r\n";\r
+    private static String exEN_WCH  =" <exitNumber>objectexitNumber-1290026472360\r\n"\r
+                                    +"    <enChild>\r\n"\r
+                                    +"        enChild content\r\n"\r
+                                    +"    </enChild>\r\n"\r
+                                    +" </exitNumber>\r\n";\r
+    private static String exNEWTREE =" <first>\r\n"\r
+                                    +"    <second>\r\n"\r
+                                    +"        second content\r\n"\r
+                                    +"    </second>\r\n"\r
+                                    +" </first>\r\n";\r
+    private static String exDEP     =" <depositor>urn:cspace:org.collectionspace.demo:orgauthority:name(TestOrgAuth):organization:name(Northern Climes Museum)'Northern Climes Museum'</depositor>\r\n";\r
+    private static String exNEW     =" <newField>objectexitNumber-1290026472360</newField>\r\n";\r
+    private static String exFOOT    ="</ns2:objectexit_common>";\r
+\r
+    private static String expectedPartContent = exHEAD + exEN + exDEP  + exFOOT;\r
+\r
+\r
+    // ============  from-server part, will be used as RIGHT tree ==========================================================\r
+\r
+    private static String srvHEAD =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"\r
+                                    +"<ns2:objectexit_common xmlns:ns2=\"http://collectionspace.org/services/objectexit\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://collectionspace.org/services/objectexit http://services.collectionspace.org/objectexit/objectexit_common.xsd\">\r\n";\r
+    private static String srvEN    = "<exitNumber>objectexitNumber-1290026472360</exitNumber>\r\n";\r
+    private static String srvEN2   = "<exitNumber>objectexitNumber-9999999999999</exitNumber>\r\n";\r
+    private static String srvDEPOSITOR  = "<depositor>urn:cspace:org.collectionspace.demo:orgauthority:name(TestOrgAuth):organization:name(Northern Climes Museum)'Northern Climes Museum'</depositor>\r\n";\r
+    private static String srvFOOT =  "</ns2:objectexit_common>\r\n";\r
+\r
+    private static String partFromServer = srvHEAD+srvEN+srvDEPOSITOR+srvFOOT;\r
+\r
+\r
+\r
+}\r
index b1ef1ed0929d02c2a83af3aaad427d120accc705..0e938788f014b9cac5c551c6e94d1984511461f6 100644 (file)
@@ -12,6 +12,7 @@
 \r
 \r
     <run controlFile="objectexit/object-exit.xml" testGroup="CRUDL" />\r
+    <run controlFile="objectexit/object-exit.xml" testGroup="domwalk" />\r
     \r
 \r
 </xmlReplayMaster>\r
index 7e3c34c7862acc092b5f181a688549e6378a5770..ca9e237385cf7f9b16226ecf996c3d144e2d3413 100644 (file)
@@ -3,8 +3,33 @@
     <auths>\r
         <!-- IMPORTANT: THESE ARE STICKY :: THEY STICK AROUND UNTIL RESET, IN EXEC ORDER OF THIS FILE. -->\r
         <auth ID="admin@collectionspace.org">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>\r
+        <auth ID="testAdministator">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>\r
     </auths>\r
     \r
+    \r
+    \r
+    <testGroup ID="domwalk" autoDeletePOSTS="true">\r
+         <test ID="oe1"  auth="test">\r
+             <method>POST</method>\r
+             <uri>/cspace-services/objectexit/</uri>\r
+             <part>\r
+                 <label>objectexit_common</label>\r
+                 <filename>objectexit/oe1.xml</filename>\r
+             </part>\r
+         </test>\r
+        <test ID="oe2">\r
+            <method>GET</method>\r
+            <uri>/cspace-services/objectexit/${oe1.CSID}</uri>\r
+            <response>\r
+                <expected level="TEXT" />\r
+                <part>\r
+                     <label>objectexit_common</label>\r
+                     <filename>objectexit/res/oe2.res.xml</filename>\r
+                 </part>\r
+             </response>\r
+        </test>\r
+    </testGroup>\r
+    \r
    <!-- ================================================================================ -->\r
     \r
      <testGroup ID="CRUDL" autoDeletePOSTS="true">\r
         <test ID="oe2">\r
             <method>GET</method>\r
             <uri>/cspace-services/objectexit/${oe1.CSID}</uri>\r
-            <reponse>oe2.res.xml</reponse>\r
+            <response>\r
+                <part>\r
+                     <label>objectexit_common</label>\r
+                     <filename>objectexit/res/oe2.res.xml</filename>\r
+                 </part>\r
+             </response>\r
         </test>\r
         <test ID="oe3">\r
              <method>POST</method>\r
index b1daed5c39bca5dd31ed1e84b742221389fff39a..35bf0cd4242761c694071fabad6780f3d28b1290 100644 (file)
@@ -3,6 +3,6 @@
 xmlns:ns2="http://collectionspace.org/services/objectexit"\r
 xmlns:ns3="http://collectionspace.org/services/jaxb">\r
   <depositor>urn:cspace:org.collectionspace.demo:orgauthority:name(TestOrgAuth):organization:name(Northern Climes Museum)'Northern Climes Museum'</depositor>\r
-  <exitNumber>objectexitNumber-1290024274266</exitNumber>\r
+  <exitNumber>objectexitNumber-1290026472360</exitNumber>\r
 </ns2:objectexit_common>\r
 \r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe6.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe6.res.xml
deleted file mode 100644 (file)
index 1485aad..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:objectexit_common_list xmlns:ns2="http://collectionspace.org/services/objectexit" xmlns:ns3="http://collectionspace.org/services/jaxb"><pageNum>0</pageNum><pageSize>40</pageSize><itemsInPage>4</itemsInPage><totalItems>4</totalItems><fieldsReturned>currentOwner|depositor|exitDate|exitMethod|exitNote|exitNumber|exitReason|packingNote|uri|csid</fieldsReturned><objectexit_list_item><exitNumber>objectexitNumber-1290026473391</exitNumber><uri>/objectexit/c5844272-0da5-4c1f-b361</uri><csid>c5844272-0da5-4c1f-b361</csid></objectexit_list_item><objectexit_list_item><exitNumber>objectexitNumber-1290026473626</exitNumber><uri>/objectexit/204b5375-5639-4dc3-8bbd</uri><csid>204b5375-5639-4dc3-8bbd</csid></objectexit_list_item><objectexit_list_item><exitNumber>objectexitNumber-1290026473860</exitNumber><uri>/objectexit/70499f68-7eba-4e63-a0ec</uri><csid>70499f68-7eba-4e63-a0ec</csid></objectexit_list_item><objectexit_list_item><exitNumber>objectexitNumber-1290026472360</exitNumber><uri>/objectexit/6f7a1e3e-5821-4ef2-bfcf</uri><csid>6f7a1e3e-5821-4ef2-bfcf</csid></objectexit_list_item></ns2:objectexit_common_list>\r
-\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe10.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe10.res.xml
new file mode 100755 (executable)
index 0000000..20ae40f
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ns2:personauthorities_common xmlns:ns2="http://collectionspace.org/services/person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://collectionspace.org/services/person http://services.collectionspace.org/person/personauthorities_common.xsd">\r
+<shortIdentifier>ObjectexitPersonAuth</shortIdentifier>\r
+<refName>urn:cspace:org.collectionspace.demo:personauthority:name(ObjectexitPersonAuth)'ObjectexitPersonAuth'</refName>\r
+<csid>${oe9.CSID}</csid>\r
+<displayName>ObjectexitPersonAuth</displayName>\r
+<vocabType>PersonAuthority</vocabType>\r
+</ns2:personauthorities_common>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe12.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe12.res.xml
new file mode 100755 (executable)
index 0000000..61e1d74
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ns2:persons_common xmlns:ns2="http://collectionspace.org/services/person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://collectionspace.org/services/person http://services.collectionspace.org/person/persons_common.xsd">\r
+<surName>Owner</surName>\r
+<nationalities/>\r
+<shortIdentifier>owenCurOwner</shortIdentifier>\r
+<shortDisplayName>Owen the Cur Owner</shortDisplayName>\r
+<schoolsOrStyles/>\r
+<foreName>Owen the Cur</foreName>\r
+<groups/>\r
+<occupations/>\r
+<displayNameComputed>true</displayNameComputed>\r
+<csid>${oe11.CSID}</csid>\r
+<shortDisplayNameComputed>true</shortDisplayNameComputed>\r
+<inAuthority>${oe9.CSID}</inAuthority>\r
+<refName>urn:cspace:org.collectionspace.demo:personauthority:name(ObjectexitPersonAuth)'ObjectexitPersonAuth':person:name(owenCurOwner)</refName>\r
+<displayName>Owen the Cur Owner</displayName>\r
+</ns2:persons_common>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe14.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe14.res.xml
new file mode 100755 (executable)
index 0000000..ba4aaee
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ns2:persons_common xmlns:ns2="http://collectionspace.org/services/person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://collectionspace.org/services/person http://services.collectionspace.org/person/persons_common.xsd">\r
+<surName>Depositor</surName>\r
+<nationalities/>\r
+<shortIdentifier>davenportDepositor</shortIdentifier>\r
+<shortDisplayName>Davenport Depositor</shortDisplayName>\r
+<schoolsOrStyles/>\r
+<foreName>Davenport</foreName>\r
+<groups/>\r
+<occupations/>\r
+<displayNameComputed>true</displayNameComputed>\r
+<csid>${oe13.CSID}</csid>\r
+<shortDisplayNameComputed>true</shortDisplayNameComputed>\r
+<inAuthority>${oe9.CSID}</inAuthority>\r
+<refName>urn:cspace:org.collectionspace.demo:personauthority:name(ObjectexitPersonAuth)'ObjectexitPersonAuth':person:name(davenportDepositor)</refName>\r
+<displayName>Davenport Depositor</displayName>\r
+</ns2:persons_common>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe16.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe16.res.xml
new file mode 100755 (executable)
index 0000000..d79e702
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ns2:objectexit_common xmlns:ns2="http://collectionspace.org/services/objectexit" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://collectionspace.org/services/objectexit http://services.collectionspace.org/objectexit/objectexit_common.xsd">\r
+<exitDate>exitDate-1290026474563</exitDate>\r
+<exitNumber>exitNumber-1290026474563</exitNumber>\r
+<depositor>urn:cspace:org.collectionspace.demo:personauthority:name(ObjectexitPersonAuth)'ObjectexitPersonAuth':person:name(davenportDepositor)</depositor>\r
+</ns2:objectexit_common>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe17.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe17.res.xml
new file mode 100755 (executable)
index 0000000..c9f6cbc
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns3:authority-ref-list xmlns:ns2="http://collectionspace.org/services/jaxb" xmlns:ns3="http://collectionspace.org/services/common/authorityref"><pageNum>0</pageNum><pageSize>40</pageSize><itemsInPage>1</itemsInPage><totalItems>1</totalItems><authority-ref-item><sourceField>objectexit_common:depositor</sourceField><refName>urn:cspace:org.collectionspace.demo:personauthority:name(ObjectexitPersonAuth)'ObjectexitPersonAuth':person:name(davenportDepositor)</refName><authDisplayName>ObjectexitPersonAuth</authDisplayName><uri>/personauthorities/urn:cspace:name(ObjectexitPersonAuth)/items/urn:cspace:name(davenportDepositor)</uri></authority-ref-item></ns3:authority-ref-list>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe2.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe2.res.xml
new file mode 100755 (executable)
index 0000000..205bc15
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ns2:objectexit_common \r
+  xmlns:ns2="http://collectionspace.org/services/objectexit" \r
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \r
+  xsi:schemaLocation="http://collectionspace.org/services/objectexit http://services.collectionspace.org/objectexit/objectexit_common.xsd">\r
+<exitNumber>objectexitNumber-1290026472360\r
+<second>\r
+        second content\r
+    </second>\r
+</exitNumber>\r
+<first>\r
+    <second>\r
+        second content\r
+    </second>\r
+</first>\r
+\r
+<depositor>urn:cspace:org.collectionspace.demo:orgauthority:name(TestOrgAuth):organization:name(Northern Climes Museum)'Northern Climes Museum'</depositor>\r
+<newField>objectexitNumber-1290026472360</newField>\r
+</ns2:objectexit_common>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe23.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe23.res.xml
new file mode 100755 (executable)
index 0000000..31e03b8
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ns2:objectexit_common xmlns:ns2="http://collectionspace.org/services/objectexit" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://collectionspace.org/services/objectexit http://services.collectionspace.org/objectexit/objectexit_common.xsd">\r
+<exitNumber>updated-objectexitNumber-1290026472360</exitNumber>\r
+<depositor>urn:cspace:org.collectionspace.demo:orgauthority:name(TestOrgAuth):organization:name(Northern Climes Museum)'Northern Climes Museum'</depositor>\r
+</ns2:objectexit_common>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe27.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe27.res.xml
new file mode 100755 (executable)
index 0000000..7c21e3e
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:objectexit_common_list xmlns:ns2="http://collectionspace.org/services/objectexit" xmlns:ns3="http://collectionspace.org/services/jaxb"><pageNum>0</pageNum><pageSize>1</pageSize><itemsInPage>1</itemsInPage><totalItems>3</totalItems><fieldsReturned>currentOwner|depositor|exitDate|exitMethod|exitNote|exitNumber|exitReason|packingNote|uri|csid</fieldsReturned><objectexit_list_item><exitNumber>objectexitNumber-1290026473391</exitNumber><uri>/objectexit/${oe3.CSID}</uri><csid>${oe3.CSID}</csid></objectexit_list_item></ns2:objectexit_common_list>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe28.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe28.res.xml
new file mode 100755 (executable)
index 0000000..7c21e3e
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:objectexit_common_list xmlns:ns2="http://collectionspace.org/services/objectexit" xmlns:ns3="http://collectionspace.org/services/jaxb"><pageNum>0</pageNum><pageSize>1</pageSize><itemsInPage>1</itemsInPage><totalItems>3</totalItems><fieldsReturned>currentOwner|depositor|exitDate|exitMethod|exitNote|exitNumber|exitReason|packingNote|uri|csid</fieldsReturned><objectexit_list_item><exitNumber>objectexitNumber-1290026473391</exitNumber><uri>/objectexit/${oe3.CSID}</uri><csid>${oe3.CSID}</csid></objectexit_list_item></ns2:objectexit_common_list>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe29.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe29.res.xml
new file mode 100755 (executable)
index 0000000..f66fb74
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:objectexit_common_list xmlns:ns2="http://collectionspace.org/services/objectexit" xmlns:ns3="http://collectionspace.org/services/jaxb"><pageNum>1</pageNum><pageSize>1</pageSize><itemsInPage>1</itemsInPage><totalItems>3</totalItems><fieldsReturned>currentOwner|depositor|exitDate|exitMethod|exitNote|exitNumber|exitReason|packingNote|uri|csid</fieldsReturned><objectexit_list_item><exitNumber>objectexitNumber-1290026473626</exitNumber><uri>/objectexit/${oe4.CSID}</uri><csid>${oe4.CSID}</csid></objectexit_list_item></ns2:objectexit_common_list>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe30.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe30.res.xml
new file mode 100755 (executable)
index 0000000..72cdfbf
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:objectexit_common_list xmlns:ns2="http://collectionspace.org/services/objectexit" xmlns:ns3="http://collectionspace.org/services/jaxb"><pageNum>2</pageNum><pageSize>1</pageSize><itemsInPage>1</itemsInPage><totalItems>3</totalItems><fieldsReturned>currentOwner|depositor|exitDate|exitMethod|exitNote|exitNumber|exitReason|packingNote|uri|csid</fieldsReturned><objectexit_list_item><exitNumber>objectexitNumber-1290026473860</exitNumber><uri>/objectexit/${oe5.CSID}</uri><csid>${oe5.CSID}</csid></objectexit_list_item></ns2:objectexit_common_list>\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe6.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe6.res.xml
new file mode 100755 (executable)
index 0000000..82e7a11
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<ns2:objectexit_common_list xmlns:ns2="http://collectionspace.org/services/objectexit" \r
+    xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+    <pageNum>0</pageNum><pageSize>40</pageSize><itemsInPage>4</itemsInPage><totalItems>4</totalItems><fieldsReturned>currentOwner|depositor|exitDate|exitMethod|exitNote|exitNumber|exitReason|packingNote|uri|csid</fieldsReturned><objectexit_list_item><exitNumber>objectexitNumber-1290026473391</exitNumber><uri>/objectexit/${oe3.CSID}</uri><csid>${oe3.CSID}</csid></objectexit_list_item><objectexit_list_item><exitNumber>objectexitNumber-1290026473626</exitNumber><uri>/objectexit/${oe4.CSID}</uri><csid>${oe4.CSID}</csid></objectexit_list_item><objectexit_list_item><exitNumber>objectexitNumber-1290026473860</exitNumber><uri>/objectexit/${oe5.CSID}</uri><csid>${oe5.CSID}</csid></objectexit_list_item><objectexit_list_item><exitNumber>objectexitNumber-1290026472360</exitNumber><uri>/objectexit/${oe1.CSID}</uri><csid>${oe1.CSID}</csid></objectexit_list_item></ns2:objectexit_common_list>\r
+\r
index 8ffee79f5820c65ed7df9212fec83fadedc41913..831c48136b9525268bfa516abe61f2b5b5c2de37 100755 (executable)
             </part>\r
         </test>\r
         <test ID="dimensionBigbird_PUT_AfterPermrolesDeleted">\r
-            <expectedCodes>403, 404,405</expectedCodes><!-- Expected failure because dimensionBigbird_POST_AfterPermrolesDeleted failed.-->\r
+            <expectedCodes>403,404,405</expectedCodes><!-- Expected failure because dimensionBigbird_POST_AfterPermrolesDeleted failed.-->\r
             <method>PUT</method>\r
             <uri>/cspace-services/dimensions/${dimensionBigbird_POST_AfterPermrolesDeleted.CSID}</uri>\r
             <part>\r
index 13c448c64d9e8e89276cdb43f9478c30a25e1d59..266689108dd1cf5bcaaf729784bd4f4b710c7e8a 100755 (executable)
@@ -21,6 +21,8 @@
     -->\r
 \r
     <run controlFile="./security.xml" testGroup="securityRemovingRoleperms" />\r
+    <run controlFile="objectexit/object-exit.xml" testGroup="CRUDL" />\r
+    <run controlFile="objectexit/object-exit.xml" testGroup="domwalk" />\r
     \r
     <!--<run controlFile="./organization.xml" testGroup="organization" />-->\r
 \r