[CalendarServer-changes] [9369] CalendarServer/trunk/contrib/performance/loadtest

source_changes at macosforge.org source_changes at macosforge.org
Mon Jun 18 11:16:57 PDT 2012


Revision: 9369
          http://trac.macosforge.org/projects/calendarserver/changeset/9369
Author:   cdaboo at apple.com
Date:     2012-06-18 11:16:57 -0700 (Mon, 18 Jun 2012)
Log Message:
-----------
Remove some hard-coded dependencies on specific paths and calendar-user addresses.

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist
    CalendarServer/trunk/contrib/performance/loadtest/config.plist
    CalendarServer/trunk/contrib/performance/loadtest/ical.py
    CalendarServer/trunk/contrib/performance/loadtest/profiles.py
    CalendarServer/trunk/contrib/performance/loadtest/sim.py
    CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
    CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py

Modified: CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist	2012-06-18 18:11:20 UTC (rev 9368)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist	2012-06-18 18:16:57 UTC (rev 9369)
@@ -34,7 +34,7 @@
 
 		<!-- Identify the server to be load tested. -->
 		<key>server</key>
-		<string>https://127.0.0.1:8443/</string>
+		<string>https://127.0.0.1:8443</string>
 
 		<!-- The template URI for doing initial principal lookup on. -->
 		<key>principalPathTemplate</key>

Modified: CalendarServer/trunk/contrib/performance/loadtest/config.plist
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/config.plist	2012-06-18 18:11:20 UTC (rev 9368)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.plist	2012-06-18 18:16:57 UTC (rev 9369)
@@ -21,7 +21,7 @@
 	<dict>
 		<!-- Identify the server to be load tested. -->
 		<key>server</key>
-		<string>https://127.0.0.1:8443/</string>
+		<string>https://127.0.0.1:8443</string>
 
 		<!-- The template URI for doing initial principal lookup on. -->
 		<key>principalPathTemplate</key>

Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/ical.py	2012-06-18 18:11:20 UTC (rev 9368)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py	2012-06-18 18:16:57 UTC (rev 9369)
@@ -380,6 +380,9 @@
         # The principalURL found during discovery
         self.principalURL = None
 
+        # The principal collection found during startup
+        self.principalCollection = None
+
         # Keep track of the events on this account, keys are event
         # URIs (which are unambiguous across different calendars
         # because they start with the uri of the calendar they are
@@ -495,7 +498,7 @@
         response = yield self._request(
             allowedStatus,
             'PROPFIND',
-            self.root + url[1:].encode('utf-8'),
+            self.root + url.encode('utf-8'),
             hdrs,
             StringProducer(body),
             method_label=method_label,
@@ -516,7 +519,7 @@
         response = yield self._request(
             (OK, MULTI_STATUS,),
             'PROPPATCH',
-            self.root + url[1:].encode('utf-8'),
+            self.root + url.encode('utf-8'),
             hdrs,
             StringProducer(body),
             method_label=method_label,
@@ -540,7 +543,7 @@
         response = yield self._request(
             allowedStatus,
             'REPORT',
-            self.root + url[1:].encode('utf-8'),
+            self.root + url.encode('utf-8'),
             hdrs,
             StringProducer(body),
             method_label=method_label,
@@ -639,6 +642,36 @@
         returnValue((calendars, result,))
 
 
+    @inlineCallbacks
+    def _extractPrincipalDetails(self):
+        # Using the actual principal URL, retrieve principal information
+        principal = yield self._principalPropfind()
+
+        hrefs = principal.getHrefProperties()
+
+        # Remember our outbox and ignore notifications
+        self.outbox = hrefs[caldavxml.schedule_outbox_URL].toString()
+        self.notificationURL = None
+
+        # Remember our own email-like principal address
+        cuaddrs = hrefs[caldavxml.calendar_user_address_set]
+        if isinstance(cuaddrs, basestring):
+            cuaddrs = (cuaddrs,)
+        for cuaddr in cuaddrs:
+            if cuaddr.toString().startswith(u"mailto:"):
+                self.email = cuaddr.toString()
+            elif cuaddr.toString().startswith(u"urn:"):
+                self.uuid = cuaddr.toString()
+        if self.email is None:
+            raise ValueError("Cannot operate without a mail-style principal URL")
+
+        # Do another kind of thing I guess
+        self.principalCollection = hrefs[davxml.principal_collection_set].toString()
+        yield self._principalSearchPropertySetReport(self.principalCollection)
+
+        returnValue(principal)
+
+
     def _extractCalendars(self, results, calendarHome=None):
         """
         Parse a calendar home PROPFIND response and create local state
@@ -1212,7 +1245,7 @@
     def _makeSelfAttendee(self):
         attendee = Property(
             name=u'ATTENDEE',
-            value=self.uuid,
+            value=self.email,
             params={
                 'CN': self.record.commonName,
                 'CUTYPE': 'INDIVIDUAL',
@@ -1225,7 +1258,7 @@
     def _makeSelfOrganizer(self):
         organizer = Property(
             name=u'ORGANIZER',
-            value=self.uuid,
+            value=self.email,
             params={
                 'CN': self.record.commonName,
             },
@@ -1263,7 +1296,7 @@
         response = yield self._request(
             (NO_CONTENT, PRECONDITION_FAILED,),
             'PUT',
-            self.root + href[1:].encode('utf-8'),
+            self.root + href.encode('utf-8'),
             Headers({
                     'content-type': ['text/calendar'],
                     'if-match': [event.etag]}),
@@ -1286,30 +1319,34 @@
             # prefix = name[:4].lower()
             prefix = random.choice(["chris", "cyru", "dre", "eric", "morg",
                 "well", "wilfr", "witz"])
+
+            email = attendee.value()
+            if email.startswith("mailto:"):
+                email = email[7:]
+            elif attendee.hasParameter('EMAIL'):
+                email = attendee.parameterValue('EMAIL').encode("utf-8")
     
-            email = attendee.parameterValue('EMAIL').encode("utf-8")
-    
             # First try to discover some names to supply to the
             # auto-completion
-            response = yield self._request(
-                MULTI_STATUS, 'REPORT', self.root + 'principals/',
-                Headers({'content-type': ['text/xml']}),
-                StringProducer(self._USER_LIST_PRINCIPAL_PROPERTY_SEARCH % {
-                        'displayname': prefix,
-                        'email': prefix,
-                        'firstname': prefix,
-                        'lastname': prefix,
-                        }),
+            yield self._report(
+                self.principalCollection,
+                self._USER_LIST_PRINCIPAL_PROPERTY_SEARCH % {
+                'displayname': prefix,
+                'email': prefix,
+                'firstname': prefix,
+                'lastname': prefix,
+                },
+                depth=None,
                 method_label="REPORT{psearch}",
-            )
-            yield readBody(response)
+           )
     
             # Now learn about the attendee's availability
             yield self.requestAvailability(
                 vevent.mainComponent().getStartDateUTC(),
                 vevent.mainComponent().getEndDateUTC(),
                 [self.email, u'mailto:' + email],
-                [vevent.resourceUID()])
+                [vevent.resourceUID()]
+            )
 
 
     @inlineCallbacks
@@ -1338,7 +1375,7 @@
         response = yield self._request(
             okCodes,
             'PUT',
-            self.root + href[1:].encode('utf-8'),
+            self.root + href.encode('utf-8'),
             headers, StringProducer(vevent.getTextWithTimezones(includeTimezones=True)),
             method_label="PUT{attendee-%s}" % (label_suffix,),
         )
@@ -1357,7 +1394,7 @@
         response = yield self._request(
             NO_CONTENT,
             'DELETE',
-            self.root + href[1:].encode('utf-8'),
+            self.root + href.encode('utf-8'),
             method_label="DELETE{event}",
         )
         returnValue(response)
@@ -1379,7 +1416,7 @@
         response = yield self._request(
             CREATED,
             'PUT',
-            self.root + href[1:].encode('utf-8'),
+            self.root + href.encode('utf-8'),
             headers,
             StringProducer(vcalendar.getTextWithTimezones(includeTimezones=True)),
             method_label="PUT{organizer-%s}" % (label_suffix,) if invite else "PUT{event}",
@@ -1397,7 +1434,7 @@
         # Do lookup and free busy of each attendee (not self)
         attendees = list(vevent.mainComponent().properties('ATTENDEE'))
         for attendee in attendees:
-            if attendee.value() == self.uuid:
+            if attendee.value() in (self.uuid, self.email):
                 continue
             yield self._attendeeAutoComplete(vevent, attendee)
         
@@ -1424,7 +1461,7 @@
         response = yield self._request(
             OK,
             'GET',
-            self.root + href[1:].encode('utf-8'),
+            self.root + href.encode('utf-8'),
             method_label="GET{event}",
         )
         headers = response.headers
@@ -1455,7 +1492,7 @@
         @return: A C{Deferred} which fires with a C{dict}.  Keys in the dict
             are user UUIDs (those requested) and values are something else.
         """
-        outbox = self.root + self.outbox[1:]
+        outbox = self.root + self.outbox
 
         if mask:
             maskStr = u'\r\n'.join(['X-CALENDARSERVER-MASK-UID:' + uid
@@ -1578,30 +1615,7 @@
             self.principalURL = hrefs[davxml.principal_URL].toString()
 
         # Using the actual principal URL, retrieve principal information
-        principal = yield self._principalPropfind()
-
-        hrefs = principal.getHrefProperties()
-
-        # Remember our outbox and notifications
-        self.outbox = hrefs[caldavxml.schedule_outbox_URL].toString()
-        try:
-            self.notificationURL = hrefs[csxml.notification_URL].toString()
-        except KeyError:
-            self.notificationURL = None
-
-        # Remember our own email-like principal address
-        for principalURL in hrefs[caldavxml.calendar_user_address_set]:
-            if principalURL.toString().startswith(u"mailto:"):
-                self.email = principalURL.toString()
-            elif principalURL.toString().startswith(u"urn:"):
-                self.uuid = principalURL.toString()
-        if self.email is None:
-            raise ValueError("Cannot operate without a mail-style principal URL")
-
-        # Do another kind of thing I guess
-        principalCollection = hrefs[davxml.principal_collection_set].toString()
-        (yield self._principalSearchPropertySetReport(principalCollection))
-
+        principal = (yield self._extractPrincipalDetails())
         returnValue(principal)
 
 
@@ -1691,30 +1705,7 @@
                 self.principalURL = hrefs[davxml.principal_URL].toString()
 
         # Using the actual principal URL, retrieve principal information
-        principal = yield self._principalPropfind()
-
-        hrefs = principal.getHrefProperties()
-
-        # Remember our outbox and notifications
-        self.outbox = hrefs[caldavxml.schedule_outbox_URL].toString()
-        try:
-            self.notificationURL = hrefs[csxml.notification_URL].toString()
-        except KeyError:
-            self.notificationURL = None
-
-        # Remember our own email-like principal address
-        for principalURL in hrefs[caldavxml.calendar_user_address_set]:
-            if principalURL.toString().startswith(u"mailto:"):
-                self.email = principalURL.toString()
-            elif principalURL.toString().startswith(u"urn:"):
-                self.uuid = principalURL.toString()
-        if self.email is None:
-            raise ValueError("Cannot operate without a mail-style principal URL")
-
-        # Do another kind of thing I guess
-        principalCollection = hrefs[davxml.principal_collection_set].toString()
-        yield self._principalSearchPropertySetReport(principalCollection)
-
+        principal = yield self._extractPrincipalDetails()
         returnValue(principal)
 
 
@@ -1779,20 +1770,6 @@
 
 
     @inlineCallbacks
-    def _principalPropfindInitial(self):
-        """
-        Issue a PROPFIND on the /principals/ URL to retrieve
-        the /principals/__uids__/<guid> principal URL
-        """
-        _ignore_response, result = yield self._propfind(
-            '/principals/',
-            self._STARTUP_PRINCIPAL_PROPFIND_INITIAL,
-            method_label="PROPFIND{find-principal}",
-        )
-        returnValue(result['/principals/'])
-
-
-    @inlineCallbacks
     def _pollFirstTime1(self, homeNode, calendars):
         # Patch calendar properties
         for cal in calendars:
@@ -1899,27 +1876,7 @@
                 self.principalURL = hrefs[davxml.principal_URL].toString()
 
         # Using the actual principal URL, retrieve principal information
-        principal = yield self._principalPropfind()
-
-        hrefs = principal.getHrefProperties()
-
-        # Remember our outbox and ignore notifications
-        self.outbox = hrefs[caldavxml.schedule_outbox_URL].toString()
-        self.notificationURL = None
-
-        # Remember our own email-like principal address
-        for principalURL in hrefs[caldavxml.calendar_user_address_set]:
-            if principalURL.toString().startswith(u"mailto:"):
-                self.email = principalURL.toString()
-            elif principalURL.toString().startswith(u"urn:"):
-                self.uuid = principalURL.toString()
-        if self.email is None:
-            raise ValueError("Cannot operate without a mail-style principal URL")
-
-        # Do another kind of thing I guess
-        principalCollection = hrefs[davxml.principal_collection_set].toString()
-        yield self._principalSearchPropertySetReport(principalCollection)
-
+        principal = yield self._extractPrincipalDetails()
         returnValue(principal)
 
 

Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py	2012-06-18 18:11:20 UTC (rev 9368)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py	2012-06-18 18:16:57 UTC (rev 9369)
@@ -174,7 +174,7 @@
         given event.
         """
         selfRecord = self._sim.getUserRecord(self._number)
-        invitees = set([u'urn:uuid:%s' % (selfRecord.uid,)])
+        invitees = set([u'mailto:%s' % (selfRecord.email,)])
         for att in attendees:
             invitees.add(att.value())
 
@@ -185,23 +185,22 @@
                 record = self._sim.getUserRecord(invitee)
             except IndexError:
                 continue
+            cuaddr = u'mailto:%s' % (record.email,)
             uuid = u'urn:uuid:%s' % (record.uid,)
-            if uuid not in invitees:
+            if cuaddr not in invitees and uuid not in invitees:
                 break
         else:
             return fail(CannotAddAttendee("Can't find uninvited user to invite."))
 
         attendee = Property(
             name=u'ATTENDEE',
-            value=uuid.encode("utf-8"),
+            value=cuaddr.encode("utf-8"),
             params={
             'CN': record.commonName,
             'CUTYPE': 'INDIVIDUAL',
-            'EMAIL': record.email,
             'PARTSTAT': 'NEEDS-ACTION',
             'ROLE': 'REQ-PARTICIPANT',
             'RSVP': 'TRUE',
-            #'SCHEDULE-STATUS': '1.2',
             },
         )
 
@@ -320,7 +319,7 @@
         given event.
         """
         selfRecord = self._sim.getUserRecord(self._number)
-        invitees = set([u'urn:uuid:%s' % (selfRecord.uid,)])
+        invitees = set([u'mailto:%s' % (selfRecord.email,)])
         for att in attendees:
             invitees.add(att.value())
 
@@ -331,23 +330,21 @@
                 record = self._sim.getUserRecord(invitee)
             except IndexError:
                 continue
-            uuid = u'urn:uuid:%s' % (record.uid,)
-            if uuid not in invitees:
+            cuaddr = u'mailto:%s' % (record.email,)
+            if cuaddr not in invitees:
                 break
         else:
             raise CannotAddAttendee("Can't find uninvited user to invite.")
 
         attendee = Property(
             name=u'ATTENDEE',
-            value=uuid.encode("utf-8"),
+            value=cuaddr.encode("utf-8"),
             params={
             'CN': record.commonName,
             'CUTYPE': 'INDIVIDUAL',
-            'EMAIL': record.email,
             'PARTSTAT': 'NEEDS-ACTION',
             'ROLE': 'REQ-PARTICIPANT',
             'RSVP': 'TRUE',
-            #'SCHEDULE-STATUS': '1.2',
             },
         )
 

Modified: CalendarServer/trunk/contrib/performance/loadtest/sim.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/sim.py	2012-06-18 18:11:20 UTC (rev 9368)
+++ CalendarServer/trunk/contrib/performance/loadtest/sim.py	2012-06-18 18:16:57 UTC (rev 9369)
@@ -242,7 +242,7 @@
             workerID = config.get("workerID", 0)
             workerCount = config.get("workerCount", 1)
             configTemplate = None
-            server = 'http://127.0.0.1:8008/'
+            server = 'http://127.0.0.1:8008'
             principalPathTemplate = "/principals/users/%s/"
             webadminPort = None
             serializationPath = None

Modified: CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_ical.py	2012-06-18 18:11:20 UTC (rev 9368)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_ical.py	2012-06-18 18:16:57 UTC (rev 9369)
@@ -1160,7 +1160,7 @@
             u"user91", u"user91", u"User 91", u"user91 at example.org")
         self.client = OS_X_10_6(
             None,
-            "http://127.0.0.1/",
+            "http://127.0.0.1",
             "/principals/users/%s/",
             None,
             self.record,
@@ -1361,12 +1361,13 @@
 
         self.client.uuid = u'urn:uuid:user01'
         self.client.email = u'mailto:user01 at example.com'
+        self.client.principalCollection = "/principals/"
         self.client.outbox = "/calendars/__uids__/user01/outbox/"
 
         @inlineCallbacks
         def _testReport(*args, **kwargs):
             expectedResponseCode, method, url, headers, body = args
-            self.assertEqual(expectedResponseCode, MULTI_STATUS)
+            self.assertEqual(expectedResponseCode, (MULTI_STATUS,))
             self.assertEqual(method, 'REPORT')
             self.assertEqual(url, 'http://127.0.0.1/principals/')
             self.assertIsInstance(url, str)
@@ -1377,7 +1378,7 @@
             
             response = MemoryResponse(
                 ('HTTP', '1', '1'), MULTI_STATUS, "MultiStatus", Headers({}),
-                StringProducer(""))
+                StringProducer("<?xml version='1.0' encoding='UTF-8'?><multistatus xmlns='DAV:' />"))
             
             returnValue(response)
             

Modified: CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py	2012-06-18 18:11:20 UTC (rev 9368)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py	2012-06-18 18:16:57 UTC (rev 9369)
@@ -278,7 +278,7 @@
     def _makeSelfAttendee(self):
         attendee = Property(
             name=u'ATTENDEE',
-            value=self.uuid,
+            value=self.email,
             params={
                 'CN': self.record.commonName,
                 'CUTYPE': 'INDIVIDUAL',
@@ -291,7 +291,7 @@
     def _makeSelfOrganizer(self):
         organizer = Property(
             name=u'ORGANIZER',
-            value=self.uuid,
+            value=self.email,
             params={
                 'CN': self.record.commonName,
             },
@@ -401,7 +401,6 @@
         for paramname, paramvalue in {
             'CN': 'User %d' % (userNumber + 1,),
             'CUTYPE': 'INDIVIDUAL',
-            'EMAIL': 'user%d at example.com' % (userNumber + 1,),
             'PARTSTAT': 'NEEDS-ACTION',
             'ROLE': 'REQ-PARTICIPANT',
             'RSVP': 'TRUE'
@@ -431,7 +430,6 @@
         for paramname, paramvalue in {
             'CN': 'User %d' % (otherNumber,),
             'CUTYPE': 'INDIVIDUAL',
-            'EMAIL': 'user%d at example.com' % (otherNumber,),
             'PARTSTAT': 'NEEDS-ACTION',
             'ROLE': 'REQ-PARTICIPANT',
             'RSVP': 'TRUE'
@@ -463,7 +461,6 @@
         for paramname, paramvalue in {
             'CN': 'User %02d' % (anotherNumber,),
             'CUTYPE': 'INDIVIDUAL',
-            'EMAIL': 'user%02d at example.com' % (anotherNumber,),
             'PARTSTAT': 'NEEDS-ACTION',
             'ROLE': 'REQ-PARTICIPANT',
             'RSVP': 'TRUE'
@@ -589,7 +586,7 @@
         inviter._invite()
         self.assertEquals(len(client._events), 1)
         attendees = tuple(client._events.values()[0].vevent.mainComponent().properties('ATTENDEE'))
-        expected = set(("urn:uuid:user%02d" %  (userNumber,), "urn:uuid:user%02d" %  (userNumber + 1,),))
+        expected = set(("mailto:user%02d at example.com" %  (userNumber,), "mailto:user%02d at example.com" %  (userNumber + 1,),))
         for attendee in attendees:
             expected.remove(attendee.value())
         self.assertEqual(len(expected), 0)
@@ -618,7 +615,7 @@
         inviter._invite()
         self.assertEquals(len(client._events), 1)
         attendees = tuple(client._events.values()[0].vevent.mainComponent().properties('ATTENDEE'))
-        expected = set(("urn:uuid:user%02d" %  (selfNumber,), "urn:uuid:user%02d" %  (otherNumber,),))
+        expected = set(("mailto:user%02d at example.com" %  (selfNumber,), "mailto:user%02d at example.com" %  (otherNumber,),))
         for attendee in attendees:
             expected.remove(attendee.value())
         self.assertEqual(len(expected), 0)
@@ -649,9 +646,9 @@
         self.assertEquals(len(client._events), 1)
         attendees = tuple(client._events.values()[0].vevent.mainComponent().properties('ATTENDEE'))
         expected = set((
-            "urn:uuid:user%02d" %  (selfNumber,),
-            "urn:uuid:user%02d" %  (inviteeNumber,),
-            "urn:uuid:user%02d" %  (anotherNumber,),
+            "mailto:user%02d at example.com" %  (selfNumber,),
+            "mailto:user%02d at example.com" %  (inviteeNumber,),
+            "mailto:user%02d at example.com" %  (anotherNumber,),
         ))
         for attendee in attendees:
             expected.remove(attendee.value())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120618/13831518/attachment-0001.html>


More information about the calendarserver-changes mailing list