[CalendarServer-changes] [6682] CalendarServer/trunk/contrib/performance/loadtest
source_changes at macosforge.org
source_changes at macosforge.org
Fri Dec 10 09:34:02 PST 2010
Revision: 6682
http://trac.macosforge.org/projects/calendarserver/changeset/6682
Author: exarkun at twistedmatrix.com
Date: 2010-12-10 09:33:58 -0800 (Fri, 10 Dec 2010)
Log Message:
-----------
Switch over from my own parsing to CalDAVClientLibrary; also add a test for learning what calendars and calendar-esque things there are.
Modified Paths:
--------------
CalendarServer/trunk/contrib/performance/loadtest/ical.py
CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/ical.py 2010-12-10 01:04:48 UTC (rev 6681)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py 2010-12-10 17:33:58 UTC (rev 6682)
@@ -15,14 +15,23 @@
#
##
-from xml.etree import ElementTree, ElementPath
+from operator import getitem
+from xml.etree import ElementTree
+ElementTree.QName.__repr__ = lambda self: '<QName %r>' % (self.text,)
+
from twisted.python.log import err
from twisted.python.filepath import FilePath
-from twisted.internet.defer import inlineCallbacks
+from twisted.internet.defer import Deferred, inlineCallbacks, returnValue
+from twisted.internet.task import LoopingCall
from twisted.web.http_headers import Headers
from twisted.web.client import Agent
+from protocol.webdav.propfindparser import PropFindParser
+from protocol.webdav.definitions import davxml
+from protocol.caldav.definitions import caldavxml
+from protocol.caldav.definitions import csxml
+
from httpclient import StringProducer, readBody
from httpauth import AuthHandlerAgent
@@ -30,82 +39,16 @@
return FilePath(__file__).sibling(label + '.request').getContent()
-class Principal(object):
+SUPPORTED_REPORT_SET = '{DAV:}supported-report-set'
- PRINCIPAL_COLLECTION_SET = '{DAV:}principal-collection-set'
- CALENDAR_HOME_SET = '{urn:ietf:params:xml:ns:caldav}calendar-home-set'
- SCHEDULE_INBOX_URL = '{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL'
- SCHEDULE_OUTBOX_URL = '{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL'
- DROPBOX_HOME_URL = '{http://calendarserver.org/ns/}dropbox-home-URL'
- NOTIFICATION_URL = '{http://calendarserver.org/ns/}notification-URL'
- DISPLAY_NAME = '{DAV:}displayname'
- PRINCIPAL_URL = '{DAV:}principal-URL'
-
- _singlePropertyNames = [
- PRINCIPAL_COLLECTION_SET,
- CALENDAR_HOME_SET,
- SCHEDULE_INBOX_URL,
- SCHEDULE_OUTBOX_URL,
- DROPBOX_HOME_URL,
- NOTIFICATION_URL,
- PRINCIPAL_URL,
- ]
- CALENDAR_USER_ADDRESS_SET = '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'
- SUPPORTED_REPORT_SET = '{DAV:}supported-report-set'
-
- _multiPropertyNames = [
- CALENDAR_USER_ADDRESS_SET, SUPPORTED_REPORT_SET]
-
-
- def __init__(self):
- self.properties = {}
-
-
- @classmethod
- def fromPROPFINDResponse(cls, response):
- """
- Construct a principal from the body a response to a
- I{PROPFIND} request for the principal URL.
-
- @type response: C{str}
- @rtype: C{cls}
- """
- principal = cls()
-
- document = ElementTree.fromstring(response)
- pattern = '{DAV:}response/{DAV:}propstat/{DAV:}prop/'
-
- name = ElementPath.find(document, pattern + cls.DISPLAY_NAME)
- if name is not None:
- principal.properties[cls.DISPLAY_NAME] = name.text
-
- for prop in cls._singlePropertyNames:
- href = ElementPath.find(document, pattern + prop + '/{DAV:}href')
- principal.properties[prop] = href.text
-
- for prop in cls._multiPropertyNames:
- hrefs = ElementPath.findall(document, pattern + prop + '/{DAV:}href')
- principal.properties[prop] = set(href.text for href in hrefs)
-
- reports = ElementPath.findall(
- document,
- pattern + cls.SUPPORTED_REPORT_SET +
- '/{DAV:}supported-report/{DAV:}report')
- supported = principal.properties[cls.SUPPORTED_REPORT_SET] = set()
- for report in reports:
- for which in report:
- supported.add(which.tag)
-
- return principal
-
-
-
class SnowLeopard(object):
"""
Implementation of the SnowLeopard iCal network behavior.
"""
+ CALENDAR_HOME_POLL_INTERVAL = 15
+
_STARTUP_PRINCIPAL_PROPFIND = loadRequestBody('sl_startup_principal_propfind')
_STARTUP_PRINCIPALS_REPORT = loadRequestBody('sl_startup_principals_report')
_STARTUP_CALENDARHOME_PROPFIND = loadRequestBody('sl_startup_calendarhome_propfind')
@@ -123,21 +66,68 @@
# XXX Do return code checking here.
return self.agent.request(method, url, headers, body)
+
+ def _parsePROPFINDResponse(self, response):
+ """
+ Construct a principal from the body a response to a
+ I{PROPFIND} request for the principal URL.
+
+ @type response: C{str}
+ @rtype: C{cls}
+ """
+ parser = PropFindParser()
+ parser.parseData(response)
+ return parser.getResults()
+
+ _CALENDAR_TYPES = set([
+ caldavxml.calendar,
+ caldavxml.schedule_inbox,
+ caldavxml.schedule_outbox,
+ csxml.notification,
+ csxml.dropbox_home,
+ ])
+ def _extractCalendars(self, response):
+ """
+ Parse
+ """
+ calendars = []
+ principals = self._parsePROPFINDResponse(response)
+
+ # XXX Here, it would be really great to somehow use
+ # CalDAVClientLibrary.client.principal.CalDAVPrincipal.listCalendars
+ for principal in principals:
+ nodes = principals[principal].getNodeProperties()
+ for nodeType in nodes[davxml.resourcetype].getchildren():
+ if nodeType.tag in self._CALENDAR_TYPES:
+ calendars.append((nodeType.tag, principals[principal]))
+ break
+ return sorted(calendars)
+
+
def _principalPropfind(self, user):
+ """
+ Issue a PROPFIND on the likely principal URL for the given
+ user and return a L{Principal} instance constructed from the
+ response.
+ """
+ principalURL = '/principals/__uids__/' + user + '/'
d = self._request(
'PROPFIND',
- self.root + 'principals/__uids__/' + user + '/',
+ self.root + principalURL[1:],
Headers({
'content-type': ['text/xml'],
'depth': ['0']}),
StringProducer(self._STARTUP_PRINCIPAL_PROPFIND))
d.addCallback(readBody)
- d.addCallback(Principal.fromPROPFINDResponse)
+ d.addCallback(self._parsePROPFINDResponse)
+ d.addCallback(getitem, principalURL)
return d
def _principalsReport(self, principalCollectionSet):
+ if principalCollectionSet.startswith('/'):
+ principalCollectionSet = principalCollectionSet[1:]
d = self._request(
'REPORT',
self.root + principalCollectionSet,
@@ -150,6 +140,10 @@
def _calendarHomePropfind(self, calendarHomeSet):
+ if calendarHomeSet.startswith('/'):
+ calendarHomeSet = calendarHomeSet[1:]
+ if not calendarHomeSet.endswith('/'):
+ calendarHomeSet = calendarHomeSet + '/'
d = self._request(
'PROPFIND',
self.root + calendarHomeSet,
@@ -158,10 +152,16 @@
'depth': ['1']}),
StringProducer(self._STARTUP_CALENDARHOME_PROPFIND))
d.addCallback(readBody)
+ d.addCallback(self._parsePROPFINDResponse)
+ def report(result):
+ print result
+ d.addCallback(report)
return d
def _notificationPropfind(self, notificationURL):
+ if notificationURL.startswith('/'):
+ notificationURL = notificationURL[1:]
d = self._request(
'PROPFIND',
self.root + notificationURL,
@@ -170,10 +170,13 @@
'depth': ['1']}),
StringProducer(self._STARTUP_NOTIFICATION_PROPFIND))
d.addCallback(readBody)
+ d.addCallback(self._extractCalendars)
return d
def _principalReport(self, principalURL):
+ if principalURL.startswith('/'):
+ principalURL = principalURL[1:]
d = self._request(
'REPORT',
self.root + principalURL,
@@ -186,34 +189,48 @@
@inlineCallbacks
- def run(self):
- """
- Emulate a CalDAV client.
- """
+ def startup(self):
# Orient ourselves, or something
principal = yield self._principalPropfind(self.user)
+ hrefs = principal.getHrefProperties()
# Do another kind of thing I guess
- principalCollectionSet = principal.properties[
- principal.PRINCIPAL_COLLECTION_SET]
- print (yield self._principalsReport(principalCollectionSet))
+ principalCollection = hrefs[caldavxml.principal_collection_set].toString()
+ print (yield self._principalsReport(principalCollection))
# Whatever
- calendarHome = principal.properties[
- principal.CALENDAR_HOME_SET]
+ calendarHome = hrefs[caldavxml.calendar_home_set].toString()
print (yield self._calendarHomePropfind(calendarHome))
# Learn stuff I guess
- notificationURL = principal.properties[
- principal.NOTIFICATION_URL]
+ notificationURL = hrefs[caldavxml.notification_URL].toString()
print (yield self._notificationPropfind(notificationURL))
# More too
- principalURL = principal.properties[
- principal.PRINCIPAL_URL]
+ principalURL = hrefs[davxml.principal_URL].toString()
print (yield self._principalReport(principalURL))
+ returnValue(principal)
+
+ @inlineCallbacks
+ def run(self):
+ """
+ Emulate a CalDAV client.
+ """
+ principal = yield self.startup()
+ hrefs = principal.getHrefProperties()
+
+ # Poll Calendar Home (and notifications?) every 15 (or
+ # whatever) minutes
+ pollCalendarHome = LoopingCall(
+ self._calendarHomePropfind,
+ hrefs[caldavxml.calendar_home_set].toString())
+ pollCalendarHome.start(self.CALENDAR_HOME_POLL_INTERVAL)
+
+ yield Deferred()
+
+
def main():
from urllib2 import HTTPDigestAuthHandler
from twisted.internet import reactor
Modified: CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_ical.py 2010-12-10 01:04:48 UTC (rev 6681)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_ical.py 2010-12-10 17:33:58 UTC (rev 6682)
@@ -17,9 +17,15 @@
from twisted.trial.unittest import TestCase
-from ical import Principal
+from protocol.url import URL
+from protocol.webdav.definitions import davxml
+from protocol.caldav.definitions import caldavxml
+from protocol.caldav.definitions import csxml
-PROPFIND_RESPONSE = """\
+from ical import SnowLeopard
+
+
+PRINCIPAL_PROPFIND_RESPONSE = """\
<?xml version='1.0' encoding='UTF-8'?>
<multistatus xmlns='DAV:'>
<response>
@@ -88,52 +94,691 @@
"""
-class PrincipalTests(TestCase):
+CALENDAR_HOME_PROPFIND_RESPONSE = """\
+<?xml version='1.0' encoding='UTF-8'?>
+<multistatus xmlns='DAV:'>
+ <response>
+ <href>/calendars/__uids__/user01/</href>
+ <propstat>
+ <prop>
+ <xmpp-server xmlns='http://calendarserver.org/ns/'/>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ <displayname>User 01</displayname>
+ <resourcetype>
+ <collection/>
+ </resourcetype>
+ <owner>
+ <href>/principals/__uids__/user01/</href>
+ </owner>
+ <quota-available-bytes>104855434</quota-available-bytes>
+ <quota-used-bytes>2166</quota-used-bytes>
+ <current-user-privilege-set>
+ <privilege>
+ <all/>
+ </privilege>
+ <privilege>
+ <read/>
+ </privilege>
+ <privilege>
+ <read-free-busy xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <write/>
+ </privilege>
+ <privilege>
+ <write-properties/>
+ </privilege>
+ <privilege>
+ <write-content/>
+ </privilege>
+ <privilege>
+ <bind/>
+ </privilege>
+ <privilege>
+ <unbind/>
+ </privilege>
+ <privilege>
+ <unlock/>
+ </privilege>
+ <privilege>
+ <read-acl/>
+ </privilege>
+ <privilege>
+ <write-acl/>
+ </privilege>
+ <privilege>
+ <read-current-user-privilege-set/>
+ </privilege>
+ </current-user-privilege-set>
+ <push-transports xmlns='http://calendarserver.org/ns/'/>
+ <pushkey xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <getctag xmlns='http://calendarserver.org/ns/'/>
+ <calendar-description xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-color xmlns='http://apple.com/ns/ical/'/>
+ <calendar-order xmlns='http://apple.com/ns/ical/'/>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-calendar-transp xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-default-calendar-URL xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-timezone xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <source xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-alarms xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-attachments xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-todos xmlns='http://calendarserver.org/ns/'/>
+ <refreshrate xmlns='http://apple.com/ns/ical/'/>
+ <publish-url xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+ <response>
+ <href>/calendars/__uids__/user01/notification/</href>
+ <propstat>
+ <prop>
+ <displayname>notification</displayname>
+ <resourcetype>
+ <collection/>
+ <notification xmlns='http://calendarserver.org/ns/'/>
+ </resourcetype>
+ <owner>
+ <href>/principals/__uids__/user01/</href>
+ </owner>
+ <quota-available-bytes>104855434</quota-available-bytes>
+ <quota-used-bytes>2166</quota-used-bytes>
+ <current-user-privilege-set>
+ <privilege>
+ <all/>
+ </privilege>
+ <privilege>
+ <read/>
+ </privilege>
+ <privilege>
+ <read-free-busy xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <write/>
+ </privilege>
+ <privilege>
+ <write-properties/>
+ </privilege>
+ <privilege>
+ <write-content/>
+ </privilege>
+ <privilege>
+ <bind/>
+ </privilege>
+ <privilege>
+ <unbind/>
+ </privilege>
+ <privilege>
+ <unlock/>
+ </privilege>
+ <privilege>
+ <read-acl/>
+ </privilege>
+ <privilege>
+ <write-acl/>
+ </privilege>
+ <privilege>
+ <read-current-user-privilege-set/>
+ </privilege>
+ </current-user-privilege-set>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <xmpp-server xmlns='http://calendarserver.org/ns/'/>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ <getctag xmlns='http://calendarserver.org/ns/'/>
+ <calendar-description xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-color xmlns='http://apple.com/ns/ical/'/>
+ <calendar-order xmlns='http://apple.com/ns/ical/'/>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-calendar-transp xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-default-calendar-URL xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-timezone xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <source xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-alarms xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-attachments xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-todos xmlns='http://calendarserver.org/ns/'/>
+ <refreshrate xmlns='http://apple.com/ns/ical/'/>
+ <push-transports xmlns='http://calendarserver.org/ns/'/>
+ <pushkey xmlns='http://calendarserver.org/ns/'/>
+ <publish-url xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+ <response>
+ <href>/calendars/__uids__/user01/dropbox/</href>
+ <propstat>
+ <prop>
+ <resourcetype>
+ <collection/>
+ <dropbox-home xmlns='http://calendarserver.org/ns/'/>
+ </resourcetype>
+ <owner>
+ <href>/principals/__uids__/user01/</href>
+ </owner>
+ <quota-available-bytes>104855434</quota-available-bytes>
+ <quota-used-bytes>2166</quota-used-bytes>
+ <current-user-privilege-set>
+ <privilege>
+ <all/>
+ </privilege>
+ <privilege>
+ <read/>
+ </privilege>
+ <privilege>
+ <read-free-busy xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <write/>
+ </privilege>
+ <privilege>
+ <write-properties/>
+ </privilege>
+ <privilege>
+ <write-content/>
+ </privilege>
+ <privilege>
+ <bind/>
+ </privilege>
+ <privilege>
+ <unbind/>
+ </privilege>
+ <privilege>
+ <unlock/>
+ </privilege>
+ <privilege>
+ <read-acl/>
+ </privilege>
+ <privilege>
+ <write-acl/>
+ </privilege>
+ <privilege>
+ <read-current-user-privilege-set/>
+ </privilege>
+ </current-user-privilege-set>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <xmpp-server xmlns='http://calendarserver.org/ns/'/>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ <getctag xmlns='http://calendarserver.org/ns/'/>
+ <displayname/>
+ <calendar-description xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-color xmlns='http://apple.com/ns/ical/'/>
+ <calendar-order xmlns='http://apple.com/ns/ical/'/>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-calendar-transp xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-default-calendar-URL xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-timezone xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <source xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-alarms xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-attachments xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-todos xmlns='http://calendarserver.org/ns/'/>
+ <refreshrate xmlns='http://apple.com/ns/ical/'/>
+ <push-transports xmlns='http://calendarserver.org/ns/'/>
+ <pushkey xmlns='http://calendarserver.org/ns/'/>
+ <publish-url xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+ <response>
+ <href>/calendars/__uids__/user01/calendar/</href>
+ <propstat>
+ <prop>
+ <getctag xmlns='http://calendarserver.org/ns/'>c2696540-4c4c-4a31-adaf-c99630776828#3</getctag>
+ <displayname>calendar</displayname>
+ <calendar-color xmlns='http://apple.com/ns/ical/'>#0252D4FF</calendar-color>
+ <calendar-order xmlns='http://apple.com/ns/ical/'>1</calendar-order>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'>
+ <comp name='VEVENT'/>
+ <comp name='VTODO'/>
+ <comp name='VTIMEZONE'/>
+ <comp name='VFREEBUSY'/>
+ </supported-calendar-component-set>
+ <resourcetype>
+ <collection/>
+ <calendar xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </resourcetype>
+ <owner>
+ <href>/principals/__uids__/user01/</href>
+ </owner>
+ <schedule-calendar-transp xmlns='urn:ietf:params:xml:ns:caldav'>
+ <opaque/>
+ </schedule-calendar-transp>
+ <quota-available-bytes>104855434</quota-available-bytes>
+ <quota-used-bytes>2166</quota-used-bytes>
+ <calendar-timezone xmlns='urn:ietf:params:xml:ns:caldav'><![CDATA[BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:America/New_York
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0500
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+DTSTART:20070311T020000
+TZNAME:EDT
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0400
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+DTSTART:20071104T020000
+TZNAME:EST
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+END:VCALENDAR
+]]></calendar-timezone>
+ <current-user-privilege-set>
+ <privilege>
+ <all/>
+ </privilege>
+ <privilege>
+ <read/>
+ </privilege>
+ <privilege>
+ <read-free-busy xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <write/>
+ </privilege>
+ <privilege>
+ <write-properties/>
+ </privilege>
+ <privilege>
+ <write-content/>
+ </privilege>
+ <privilege>
+ <bind/>
+ </privilege>
+ <privilege>
+ <unbind/>
+ </privilege>
+ <privilege>
+ <unlock/>
+ </privilege>
+ <privilege>
+ <read-acl/>
+ </privilege>
+ <privilege>
+ <write-acl/>
+ </privilege>
+ <privilege>
+ <read-current-user-privilege-set/>
+ </privilege>
+ </current-user-privilege-set>
+ <pushkey xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <xmpp-server xmlns='http://calendarserver.org/ns/'/>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ <calendar-description xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-default-calendar-URL xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <source xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-alarms xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-attachments xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-todos xmlns='http://calendarserver.org/ns/'/>
+ <refreshrate xmlns='http://apple.com/ns/ical/'/>
+ <push-transports xmlns='http://calendarserver.org/ns/'/>
+ <publish-url xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+ <response>
+ <href>/calendars/__uids__/user01/outbox/</href>
+ <propstat>
+ <prop>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'>
+ <comp name='VEVENT'/>
+ <comp name='VTODO'/>
+ <comp name='VTIMEZONE'/>
+ <comp name='VFREEBUSY'/>
+ </supported-calendar-component-set>
+ <resourcetype>
+ <collection/>
+ <schedule-outbox xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </resourcetype>
+ <owner>
+ <href>/principals/__uids__/user01/</href>
+ </owner>
+ <quota-available-bytes>104855434</quota-available-bytes>
+ <quota-used-bytes>2166</quota-used-bytes>
+ <current-user-privilege-set>
+ <privilege>
+ <all/>
+ </privilege>
+ <privilege>
+ <read/>
+ </privilege>
+ <privilege>
+ <write/>
+ </privilege>
+ <privilege>
+ <write-properties/>
+ </privilege>
+ <privilege>
+ <write-content/>
+ </privilege>
+ <privilege>
+ <bind/>
+ </privilege>
+ <privilege>
+ <unbind/>
+ </privilege>
+ <privilege>
+ <unlock/>
+ </privilege>
+ <privilege>
+ <read-acl/>
+ </privilege>
+ <privilege>
+ <write-acl/>
+ </privilege>
+ <privilege>
+ <read-current-user-privilege-set/>
+ </privilege>
+ <privilege>
+ <schedule-send xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <schedule xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <read-free-busy xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ </current-user-privilege-set>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <xmpp-server xmlns='http://calendarserver.org/ns/'/>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ <getctag xmlns='http://calendarserver.org/ns/'/>
+ <displayname/>
+ <calendar-description xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-color xmlns='http://apple.com/ns/ical/'/>
+ <calendar-order xmlns='http://apple.com/ns/ical/'/>
+ <calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-calendar-transp xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-default-calendar-URL xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-timezone xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <source xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-alarms xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-attachments xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-todos xmlns='http://calendarserver.org/ns/'/>
+ <refreshrate xmlns='http://apple.com/ns/ical/'/>
+ <push-transports xmlns='http://calendarserver.org/ns/'/>
+ <pushkey xmlns='http://calendarserver.org/ns/'/>
+ <publish-url xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+ <response>
+ <href>/calendars/__uids__/user01/freebusy</href>
+ <propstat>
+ <prop>
+ <resourcetype>
+ <free-busy-url xmlns='http://calendarserver.org/ns/'/>
+ </resourcetype>
+ <owner>
+ <href>/principals/__uids__/user01/</href>
+ </owner>
+ <quota-available-bytes>104855434</quota-available-bytes>
+ <quota-used-bytes>2166</quota-used-bytes>
+ <current-user-privilege-set>
+ <privilege>
+ <read/>
+ </privilege>
+ <privilege>
+ <schedule-deliver xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <schedule xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <all/>
+ </privilege>
+ <privilege>
+ <write/>
+ </privilege>
+ <privilege>
+ <write-properties/>
+ </privilege>
+ <privilege>
+ <write-content/>
+ </privilege>
+ <privilege>
+ <bind/>
+ </privilege>
+ <privilege>
+ <unbind/>
+ </privilege>
+ <privilege>
+ <unlock/>
+ </privilege>
+ <privilege>
+ <read-acl/>
+ </privilege>
+ <privilege>
+ <write-acl/>
+ </privilege>
+ <privilege>
+ <read-current-user-privilege-set/>
+ </privilege>
+ <privilege>
+ <read-free-busy xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ </current-user-privilege-set>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <xmpp-server xmlns='http://calendarserver.org/ns/'/>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ <getctag xmlns='http://calendarserver.org/ns/'/>
+ <displayname/>
+ <calendar-description xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-color xmlns='http://apple.com/ns/ical/'/>
+ <calendar-order xmlns='http://apple.com/ns/ical/'/>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-calendar-transp xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <schedule-default-calendar-URL xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-timezone xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <source xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-alarms xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-attachments xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-todos xmlns='http://calendarserver.org/ns/'/>
+ <refreshrate xmlns='http://apple.com/ns/ical/'/>
+ <push-transports xmlns='http://calendarserver.org/ns/'/>
+ <pushkey xmlns='http://calendarserver.org/ns/'/>
+ <publish-url xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+ <response>
+ <href>/calendars/__uids__/user01/inbox/</href>
+ <propstat>
+ <prop>
+ <getctag xmlns='http://calendarserver.org/ns/'>a483dab3-1391-445b-b1c3-5ae9dfc81c2f#0</getctag>
+ <displayname>inbox</displayname>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'>
+ <comp name='VEVENT'/>
+ <comp name='VTODO'/>
+ <comp name='VTIMEZONE'/>
+ <comp name='VFREEBUSY'/>
+ </supported-calendar-component-set>
+ <resourcetype>
+ <collection/>
+ <schedule-inbox xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </resourcetype>
+ <owner>
+ <href>/principals/__uids__/user01/</href>
+ </owner>
+ <calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/calendar</href>
+ </calendar-free-busy-set>
+ <schedule-default-calendar-URL xmlns='urn:ietf:params:xml:ns:caldav'>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/calendar</href>
+ </schedule-default-calendar-URL>
+ <quota-available-bytes>104855434</quota-available-bytes>
+ <quota-used-bytes>2166</quota-used-bytes>
+ <current-user-privilege-set>
+ <privilege>
+ <schedule-deliver xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <schedule xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ <privilege>
+ <all/>
+ </privilege>
+ <privilege>
+ <read/>
+ </privilege>
+ <privilege>
+ <write/>
+ </privilege>
+ <privilege>
+ <write-properties/>
+ </privilege>
+ <privilege>
+ <write-content/>
+ </privilege>
+ <privilege>
+ <bind/>
+ </privilege>
+ <privilege>
+ <unbind/>
+ </privilege>
+ <privilege>
+ <unlock/>
+ </privilege>
+ <privilege>
+ <read-acl/>
+ </privilege>
+ <privilege>
+ <write-acl/>
+ </privilege>
+ <privilege>
+ <read-current-user-privilege-set/>
+ </privilege>
+ <privilege>
+ <read-free-busy xmlns='urn:ietf:params:xml:ns:caldav'/>
+ </privilege>
+ </current-user-privilege-set>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <xmpp-server xmlns='http://calendarserver.org/ns/'/>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ <calendar-description xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-color xmlns='http://apple.com/ns/ical/'/>
+ <calendar-order xmlns='http://apple.com/ns/ical/'/>
+ <schedule-calendar-transp xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <calendar-timezone xmlns='urn:ietf:params:xml:ns:caldav'/>
+ <source xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-alarms xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-attachments xmlns='http://calendarserver.org/ns/'/>
+ <subscribed-strip-todos xmlns='http://calendarserver.org/ns/'/>
+ <refreshrate xmlns='http://apple.com/ns/ical/'/>
+ <push-transports xmlns='http://calendarserver.org/ns/'/>
+ <pushkey xmlns='http://calendarserver.org/ns/'/>
+ <publish-url xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+</multistatus>
+"""
+
+
+
+
+class SnowLeopardTests(TestCase):
"""
- Tests for L{Principal}, a class for representing "a distinct human
- or computational actor that initiates access to network
- resources." (U{http://tools.ietf.org/html/rfc4918})
+ Tests for L{SnowLeopard}.
"""
- def test_fromPROPFINDResponse(self):
+ def setUp(self):
+ self.client = SnowLeopard(None, "127.0.0.1", 80, None, None)
+
+
+ def test_parsePrincipalPROPFINDResponse(self):
"""
- L{Principal.fromPROPFINDResponse} accepts an XML document like
- the one returned from a I{PROPFIND /principals/__uids__/<uid>}
- and extracts all of the properties from it.
+ L{Principal._parsePROPFINDResponse} accepts an XML document
+ like the one in the response to a I{PROPFIND} request for
+ I{/principals/__uids__/<uid>/} and returns a C{PropFindResult}
+ representing the data from it.
"""
- principal = Principal.fromPROPFINDResponse(PROPFIND_RESPONSE)
+ principals = self.client._parsePROPFINDResponse(PRINCIPAL_PROPFIND_RESPONSE)
+ principal = principals['/principals/__uids__/user01/']
self.assertEquals(
- principal.properties,
- {Principal.PRINCIPAL_COLLECTION_SET: '/principals/',
- Principal.CALENDAR_HOME_SET: '/calendars/__uids__/user01',
- Principal.CALENDAR_USER_ADDRESS_SET: set([
- '/principals/__uids__/user01/',
- '/principals/users/user01/',
- ]),
- Principal.SCHEDULE_INBOX_URL: '/calendars/__uids__/user01/inbox/',
- Principal.SCHEDULE_OUTBOX_URL: '/calendars/__uids__/user01/outbox/',
- Principal.DROPBOX_HOME_URL: '/calendars/__uids__/user01/dropbox/',
- Principal.NOTIFICATION_URL: '/calendars/__uids__/user01/notification/',
- Principal.DISPLAY_NAME: 'User 01',
- Principal.PRINCIPAL_URL: '/principals/__uids__/user01/',
- Principal.SUPPORTED_REPORT_SET: set([
- '{DAV:}acl-principal-prop-set',
- '{DAV:}principal-match',
- '{DAV:}principal-property-search',
- '{DAV:}expand-property',
- ]),
+ principal.getHrefProperties(),
+ {davxml.principal_collection_set: URL(path='/principals/'),
+ caldavxml.calendar_home_set: URL(path='/calendars/__uids__/user01'),
+ caldavxml.calendar_user_address_set: (
+ URL(path='/principals/__uids__/user01/'),
+ URL(path='/principals/users/user01/'),
+ ),
+ caldavxml.schedule_inbox_URL: URL(path='/calendars/__uids__/user01/inbox/'),
+ caldavxml.schedule_outbox_URL: URL(path='/calendars/__uids__/user01/outbox/'),
+ csxml.dropbox_home_URL: URL(path='/calendars/__uids__/user01/dropbox/'),
+ csxml.notification_URL: URL(path='/calendars/__uids__/user01/notification/'),
+ davxml.principal_URL: URL(path='/principals/__uids__/user01/'),
})
+ self.assertEquals(
+ principal.getTextProperties(),
+ {davxml.displayname: 'User 01'})
+# self.assertEquals(
+# principal.getSomething(),
+# {SUPPORTED_REPORT_SET: (
+# '{DAV:}acl-principal-prop-set',
+# '{DAV:}principal-match',
+# '{DAV:}principal-property-search',
+# '{DAV:}expand-property',
+# )})
-class SnowLeopardTests(TestCase):
- """
- Tests for L{SnowLeopard}.
- """
- def test_findCalendars(self):
+
+ def test_extractCalendars(self):
"""
- L{SnowLeopard._findCalendars} accepts a calendar home PROPFIND
- response body and returns a list of calendar identifiers
- extracted from it.
+ L{SnowLeopard._extractCalendars} accepts a calendar home
+ PROPFIND response body and returns a list of calendar objects
+ constructed from the data extracted from the response.
"""
- client = SnowLeopard(None, None, None, None)
- client._findCalendars()
-
+ calendars = self.client._extractCalendars(CALENDAR_HOME_PROPFIND_RESPONSE)
+ resourceTypes = [resourceType for (resourceType, element) in calendars]
+ self.assertEquals(
+ resourceTypes,
+ sorted([csxml.dropbox_home,
+ csxml.notification,
+ caldavxml.calendar,
+ caldavxml.schedule_inbox,
+ caldavxml.schedule_outbox]))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101210/41e69988/attachment-0001.html>
More information about the calendarserver-changes
mailing list