[CalendarServer-changes] [6670] CalendarServer/trunk/contrib/performance/loadtest
source_changes at macosforge.org
source_changes at macosforge.org
Fri Dec 3 13:49:47 PST 2010
Revision: 6670
http://trac.macosforge.org/projects/calendarserver/changeset/6670
Author: exarkun at twistedmatrix.com
Date: 2010-12-03 13:49:42 -0800 (Fri, 03 Dec 2010)
Log Message:
-----------
Parse some of what the server sends back; use it to construct some of the later queries.
Modified Paths:
--------------
CalendarServer/trunk/contrib/performance/loadtest/ical.py
Added Paths:
-----------
CalendarServer/trunk/contrib/performance/loadtest/__init__.py
CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
Added: CalendarServer/trunk/contrib/performance/loadtest/__init__.py
===================================================================
Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/ical.py 2010-12-03 18:05:31 UTC (rev 6669)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py 2010-12-03 21:49:42 UTC (rev 6670)
@@ -15,6 +15,8 @@
#
##
+from xml.etree import ElementTree, ElementPath
+
from twisted.python.log import err
from twisted.python.filepath import FilePath
from twisted.internet.defer import inlineCallbacks
@@ -29,6 +31,37 @@
class Principal(object):
+
+ 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):
"""
@@ -38,10 +71,36 @@
@type response: C{str}
@rtype: C{cls}
"""
- return 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.
@@ -74,13 +133,14 @@
'depth': ['0']}),
StringProducer(self._STARTUP_PRINCIPAL_PROPFIND))
d.addCallback(readBody)
+ d.addCallback(Principal.fromPROPFINDResponse)
return d
- def _principalsReport(self):
+ def _principalsReport(self, principalCollectionSet):
d = self._request(
'REPORT',
- self.root + 'principals/',
+ self.root + principalCollectionSet,
Headers({
'content-type': ['text/xml'],
'depth': ['0']}),
@@ -89,10 +149,10 @@
return d
- def _calendarHomePropfind(self, user):
+ def _calendarHomePropfind(self, calendarHomeSet):
d = self._request(
'PROPFIND',
- self.root + 'calendars/__uids__/' + user + '/',
+ self.root + calendarHomeSet,
Headers({
'content-type': ['text/xml'],
'depth': ['1']}),
@@ -101,10 +161,10 @@
return d
- def _notificationPropfind(self, user):
+ def _notificationPropfind(self, notificationURL):
d = self._request(
'PROPFIND',
- self.root + 'calendars/__uids__/' + user + '/notification/',
+ self.root + notificationURL,
Headers({
'content-type': ['text/xml'],
'depth': ['1']}),
@@ -113,10 +173,10 @@
return d
- def _principalReport(self, user):
+ def _principalReport(self, principalURL):
d = self._request(
'REPORT',
- self.root + 'principals/__uids__/' + user + '/',
+ self.root + principalURL,
Headers({
'content-type': ['text/xml'],
'depth': ['0']}),
@@ -131,19 +191,27 @@
Emulate a CalDAV client.
"""
# Orient ourselves, or something
- print (yield self._principalPropfind(self.user))
+ principal = yield self._principalPropfind(self.user)
# Do another kind of thing I guess
- print (yield self._principalsReport())
+ principalCollectionSet = principal.properties[
+ principal.PRINCIPAL_COLLECTION_SET]
+ print (yield self._principalsReport(principalCollectionSet))
# Whatever
- print (yield self._calendarHomePropfind(self.user))
+ calendarHome = principal.properties[
+ principal.CALENDAR_HOME_SET]
+ print (yield self._calendarHomePropfind(calendarHome))
# Learn stuff I guess
- print (yield self._notificationPropfind(self.user))
+ notificationURL = principal.properties[
+ principal.NOTIFICATION_URL]
+ print (yield self._notificationPropfind(notificationURL))
# More too
- print (yield self._principalReport(self.user))
+ principalURL = principal.properties[
+ principal.PRINCIPAL_URL]
+ print (yield self._principalReport(principalURL))
def main():
Added: CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_ical.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_ical.py 2010-12-03 21:49:42 UTC (rev 6670)
@@ -0,0 +1,139 @@
+##
+# Copyright (c) 2010 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+##
+
+from twisted.trial.unittest import TestCase
+
+from ical import Principal
+
+PROPFIND_RESPONSE = """\
+<?xml version='1.0' encoding='UTF-8'?>
+<multistatus xmlns='DAV:'>
+ <response>
+ <href>/principals/__uids__/user01/</href>
+ <propstat>
+ <prop>
+ <principal-collection-set>
+ <href>/principals/</href>
+ </principal-collection-set>
+ <calendar-home-set xmlns='urn:ietf:params:xml:ns:caldav'>
+ <href xmlns='DAV:'>/calendars/__uids__/user01</href>
+ </calendar-home-set>
+ <calendar-user-address-set xmlns='urn:ietf:params:xml:ns:caldav'>
+ <href xmlns='DAV:'>/principals/__uids__/user01/</href>
+ <href xmlns='DAV:'>/principals/users/user01/</href>
+ </calendar-user-address-set>
+ <schedule-inbox-URL xmlns='urn:ietf:params:xml:ns:caldav'>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/inbox/</href>
+ </schedule-inbox-URL>
+ <schedule-outbox-URL xmlns='urn:ietf:params:xml:ns:caldav'>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/outbox/</href>
+ </schedule-outbox-URL>
+ <dropbox-home-URL xmlns='http://calendarserver.org/ns/'>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/dropbox/</href>
+ </dropbox-home-URL>
+ <notification-URL xmlns='http://calendarserver.org/ns/'>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/notification/</href>
+ </notification-URL>
+ <displayname>User 01</displayname>
+ <principal-URL>
+ <href>/principals/__uids__/user01/</href>
+ </principal-URL>
+ <supported-report-set>
+ <supported-report>
+ <report>
+ <acl-principal-prop-set/>
+ </report>
+ </supported-report>
+ <supported-report>
+ <report>
+ <principal-match/>
+ </report>
+ </supported-report>
+ <supported-report>
+ <report>
+ <principal-property-search/>
+ </report>
+ </supported-report>
+ <supported-report>
+ <report>
+ <expand-property/>
+ </report>
+ </supported-report>
+ </supported-report-set>
+ </prop>
+ <status>HTTP/1.1 200 OK</status>
+ </propstat>
+ <propstat>
+ <prop>
+ <xmpp-uri xmlns='http://calendarserver.org/ns/'/>
+ </prop>
+ <status>HTTP/1.1 404 Not Found</status>
+ </propstat>
+ </response>
+</multistatus>
+"""
+
+
+class PrincipalTests(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})
+ """
+ def test_fromPROPFINDResponse(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.
+ """
+ principal = Principal.fromPROPFINDResponse(PROPFIND_RESPONSE)
+ 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',
+ ]),
+ })
+
+
+class SnowLeopardTests(TestCase):
+ """
+ Tests for L{SnowLeopard}.
+ """
+ def test_findCalendars(self):
+ """
+ L{SnowLeopard._findCalendars} accepts a calendar home PROPFIND
+ response body and returns a list of calendar identifiers
+ extracted from it.
+ """
+ client = SnowLeopard(None, None, None, None)
+ client._findCalendars()
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101203/153b093f/attachment-0001.html>
More information about the calendarserver-changes
mailing list