[CalendarServer-changes] [9917] CalDAVTester/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Oct 10 08:51:13 PDT 2012


Revision: 9917
          http://trac.calendarserver.org//changeset/9917
Author:   cdaboo at apple.com
Date:     2012-10-10 08:51:13 -0700 (Wed, 10 Oct 2012)
Log Message:
-----------
Expand XML xpath-style tests to target sub-tree's within a document (useful for checking properties of specific
resources in Depth:1 responses). Add a sharing test for Depth:1.

Modified Paths:
--------------
    CalDAVTester/trunk/README.txt
    CalDAVTester/trunk/scripts/server/serverinfo-partitioning.xml
    CalDAVTester/trunk/scripts/server/serverinfo-template.xml
    CalDAVTester/trunk/scripts/server/serverinfo.xml
    CalDAVTester/trunk/scripts/tests/CalDAV/sharing-calendars.xml
    CalDAVTester/trunk/verifiers/xmlElementMatch.py

Modified: CalDAVTester/trunk/README.txt
===================================================================
--- CalDAVTester/trunk/README.txt	2012-10-09 23:54:56 UTC (rev 9916)
+++ CalDAVTester/trunk/README.txt	2012-10-10 15:51:13 UTC (rev 9917)
@@ -616,9 +616,22 @@
 	Compares the response with an XML data file and returns TRUE if there
 	is a match, otherwise False.
 	The path is the absolute xpath from the root element down. Attribute, attribute-value
-	and text contents tests of the matched element can be done using [@attr], [@attr="value"],
-	and [="text"] suffixes on the path.
+	and text contents tests of the matched element can be done using:
 	
+	[@attr] - "attr" is present as an attribute
+	[@attr=value] - "attr" is present as an attribute with the value "value"
+	[=text] - node text is "text".
+	[!text] - node text is not "text".
+	[*text] - node text contains "text".
+	[+text] - node text starts with "text".
+	[^tag] - node has child element "tag".
+	[^tag=text] - node has child element "tag" with text "text".
+	
+	Argument: 'parent'
+		ElementTree style path for an XML element to use as the root for any
+		subsequent "exists" or "notexists" tests. This is useful for targeting
+		a specific resource in a Depth:1 multistatus response.
+	
 	Argument: 'exists'
 		ElementTree style path for an XML element to check the presence of
 		in the response.

Modified: CalDAVTester/trunk/scripts/server/serverinfo-partitioning.xml
===================================================================
--- CalDAVTester/trunk/scripts/server/serverinfo-partitioning.xml	2012-10-09 23:54:56 UTC (rev 9916)
+++ CalDAVTester/trunk/scripts/server/serverinfo-partitioning.xml	2012-10-10 15:51:13 UTC (rev 9917)
@@ -92,7 +92,7 @@
 		<!-- CardDAV specific extension -->
 		<feature>carddav</feature> 						<!-- Basic CardDAV feature enabler -->
 		<feature>default-addressbook</feature> 			<!-- Default address book behavior -->
-		<!-- <feature>global-addressbook</feature> -->	<!-- Global address book for each user -->
+		<!-- <feature>global-addressbook</feature> --> 	<!-- Global address book for each user -->
 		<feature>shared-addressbooks</feature>			<!-- Shared address books extension -->
 		<!-- <feature>directory-gateway</feature> -->	<!-- Directory gateway extension -->
 
@@ -101,10 +101,18 @@
 	<substitutions>
 		<!-- Useful xpath shortcuts for verifiers -->
 		<substitution>
+			<key>$multistatus-response-prefix:</key>
+			<value>/{DAV:}multistatus/{DAV:}response</value>
+		</substitution>
+		<substitution>
 			<key>$multistatus-href-prefix:</key>
 			<value>/{DAV:}multistatus/{DAV:}response/{DAV:}href</value>
 		</substitution>
 		<substitution>
+			<key>$verify-response-prefix:</key>
+			<value>{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
+		</substitution>
+		<substitution>
 			<key>$verify-property-prefix:</key>
 			<value>/{DAV:}multistatus/{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
 		</substitution>

Modified: CalDAVTester/trunk/scripts/server/serverinfo-template.xml
===================================================================
--- CalDAVTester/trunk/scripts/server/serverinfo-template.xml	2012-10-09 23:54:56 UTC (rev 9916)
+++ CalDAVTester/trunk/scripts/server/serverinfo-template.xml	2012-10-10 15:51:13 UTC (rev 9917)
@@ -101,10 +101,18 @@
 	<substitutions>
 		<!-- Useful xpath shortcuts for verifiers -->
 		<substitution>
+			<key>$multistatus-response-prefix:</key>
+			<value>/{DAV:}multistatus/{DAV:}response</value>
+		</substitution>
+		<substitution>
 			<key>$multistatus-href-prefix:</key>
 			<value>/{DAV:}multistatus/{DAV:}response/{DAV:}href</value>
 		</substitution>
 		<substitution>
+			<key>$verify-response-prefix:</key>
+			<value>{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
+		</substitution>
+		<substitution>
 			<key>$verify-property-prefix:</key>
 			<value>/{DAV:}multistatus/{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
 		</substitution>

Modified: CalDAVTester/trunk/scripts/server/serverinfo.xml
===================================================================
--- CalDAVTester/trunk/scripts/server/serverinfo.xml	2012-10-09 23:54:56 UTC (rev 9916)
+++ CalDAVTester/trunk/scripts/server/serverinfo.xml	2012-10-10 15:51:13 UTC (rev 9917)
@@ -101,10 +101,18 @@
 	<substitutions>
 		<!-- Useful xpath shortcuts for verifiers -->
 		<substitution>
+			<key>$multistatus-response-prefix:</key>
+			<value>/{DAV:}multistatus/{DAV:}response</value>
+		</substitution>
+		<substitution>
 			<key>$multistatus-href-prefix:</key>
 			<value>/{DAV:}multistatus/{DAV:}response/{DAV:}href</value>
 		</substitution>
 		<substitution>
+			<key>$verify-response-prefix:</key>
+			<value>{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
+		</substitution>
+		<substitution>
 			<key>$verify-property-prefix:</key>
 			<value>/{DAV:}multistatus/{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
 		</substitution>

Modified: CalDAVTester/trunk/scripts/tests/CalDAV/sharing-calendars.xml
===================================================================
--- CalDAVTester/trunk/scripts/tests/CalDAV/sharing-calendars.xml	2012-10-09 23:54:56 UTC (rev 9916)
+++ CalDAVTester/trunk/scripts/tests/CalDAV/sharing-calendars.xml	2012-10-10 15:51:13 UTC (rev 9917)
@@ -130,6 +130,8 @@
 					<arg>
 						<name>exists</name>
 						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:caldav}calendar</value>
 						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
 						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
 						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
@@ -146,6 +148,45 @@
 			</request>
 		</test>
 		<test name='4a'>
+			<description>Shared calendar exists Depth:1</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-write/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>parent</name>
+						<value>$multistatus-response-prefix:[^{DAV:}href=$sharedcalendar:/]</value>
+					</arg>
+					<arg>
+						<name>exists</name>
+						<value>$verify-response-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-response-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+						<value>$verify-response-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:caldav}calendar</value>
+						<value>$verify-response-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-response-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4b'>
 			<description>Shared calendar has invite property</description>
 			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
 				<method>PROPFIND</method>

Modified: CalDAVTester/trunk/verifiers/xmlElementMatch.py
===================================================================
--- CalDAVTester/trunk/verifiers/xmlElementMatch.py	2012-10-09 23:54:56 UTC (rev 9916)
+++ CalDAVTester/trunk/verifiers/xmlElementMatch.py	2012-10-10 15:51:13 UTC (rev 9917)
@@ -26,6 +26,7 @@
 
     def verify(self, manager, uri, response, respdata, args): #@UnusedVariable
         # Get arguments
+        parent = args.get("parent", [])
         exists = args.get("exists", [])
         notexists = args.get("notexists", [])
 
@@ -49,16 +50,26 @@
             else:
                 return path, None
 
+        if parent:
+            nodes = self.nodeForPath(tree.getroot(), parent[0])
+            if len(nodes) == 0:
+                return False, "        Response data is missing parent node: %s" % (parent[0],)
+            elif len(nodes) > 1:
+                return False, "        Response data has too many parent nodes: %s" % (parent[0],)
+            root = nodes[0]
+        else:
+            root = tree.getroot()
+
         result = True
         resulttxt = ""
         for path in exists:
 
-            matched, txt = self.matchPath(tree, path)
+            matched, txt = self.matchPath(root, path)
             result &= matched
             resulttxt += txt
 
         for path in notexists:
-            matched, _ignore_txt = self.matchPath(tree, path)
+            matched, _ignore_txt = self.matchPath(root, path)
             if matched:
                 resulttxt += "        Items returned in XML for %s\n" % (path,)
                 result = False
@@ -66,8 +77,73 @@
         return result, resulttxt
 
 
-    def matchPath(self, tree, path):
+    def nodeForPath(self, root, path):
+        if '[' in path:
+            actual_path, tests = path.split('[', 1)
+        else:
+            actual_path = path
+            tests = None
 
+        # Handle absolute root element
+        if actual_path[0] == '/':
+            actual_path = actual_path[1:]
+        if '/' in actual_path:
+            root_path, child_path = actual_path.split('/', 1)
+            if root.tag != root_path:
+                return None
+            nodes = root.findall(child_path)
+        else:
+            root_path = actual_path
+            child_path = None
+            nodes = (root,)
+
+        if len(nodes) == 0:
+            return None
+
+        results = []
+
+        if tests:
+            tests = [item[:-1] for item in tests.split('[')]
+            for test in tests:
+                for node in nodes:
+                    if test[0] == '@':
+                        if '=' in test:
+                            attr, value = test[1:].split('=')
+                            value = value[1:-1]
+                        else:
+                            attr = test[1:]
+                            value = None
+                        if attr in node.keys() and (value is None or node.get(attr) == value):
+                            results.append(node)
+                    elif test[0] == '=':
+                        if node.text == test[1:]:
+                            results.append(node)
+                    elif test[0] == '!':
+                        if node.text != test[1:]:
+                            results.append(node)
+                    elif test[0] == '*':
+                        if node.text is not None and node.text.find(test[1:]) != -1:
+                            results.append(node)
+                    elif test[0] == '+':
+                        if node.text is not None and node.text.startswith(test[1:]):
+                            results.append(node)
+                    elif test[0] == '^':
+                        if "=" in test:
+                            element, value = test[1:].split("=", 1)
+                        else:
+                            element = test[1:]
+                            value = None
+                        for child in node.getchildren():
+                            if child.tag == element and (value is None or child.text == value):
+                                results.append(node)
+        else:
+            results = nodes
+
+        return results
+
+
+    def matchPath(self, root, path):
+
         result = True
         resulttxt = ""
 
@@ -82,13 +158,11 @@
             actual_path = actual_path[1:]
         if '/' in actual_path:
             root_path, child_path = actual_path.split('/', 1)
-            if tree.getroot().tag != root_path:
+            if root.tag != root_path:
                 resulttxt += "        Items not returned in XML for %s\n" % (path,)
-            nodes = tree.findall(child_path)
+            nodes = root.findall(child_path)
         else:
-            root_path = actual_path
-            child_path = None
-            nodes = (tree.getroot(),)
+            nodes = (root,)
 
         if len(nodes) == 0:
             resulttxt += "        Items not returned in XML for %s\n" % (path,)
@@ -125,6 +199,17 @@
                         elif test[0] == '+':
                             if node.text is None or not node.text.startswith(test[1:]):
                                 result = "        Incorrect value returned in XML for %s\n" % (path,)
+                        elif test[0] == '^':
+                            if "=" in test:
+                                element, value = test[1:].split("=", 1)
+                            else:
+                                element = test[1:]
+                                value = None
+                            for child in node.getchildren():
+                                if child.tag == element and (value is None or child.text == value):
+                                    break
+                            else:
+                                result = "        Missing child returned in XML for %s\n" % (path,)
                         return result
 
                     testresult = _doTest()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121010/84f46d73/attachment-0001.html>


More information about the calendarserver-changes mailing list