<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[15300] CalendarServer/trunk/contrib/performance/loadtest</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/15300">15300</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2015-11-09 16:00:49 -0800 (Mon, 09 Nov 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Client sim fixes: don't try to modify or attach to a scheduled event; adds an AlarmAcknowledger profile that stampedes at specified times past the hour</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunkcontribperformanceloadtestclientsplist">CalendarServer/trunk/contrib/performance/loadtest/clients.plist</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestprofilespy">CalendarServer/trunk/contrib/performance/loadtest/profiles.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtesttest_profilespy">CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunkcontribperformanceloadtestclientsplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/clients.plist (15299 => 15300)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/clients.plist        2015-11-07 04:54:31 UTC (rev 15299)
+++ CalendarServer/trunk/contrib/performance/loadtest/clients.plist        2015-11-10 00:00:49 UTC (rev 15300)
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx">                                                         <!-- Define the interval (in seconds) at which this profile will use
</span><span class="cx">                                                                 its client to create a new event. -->
</span><span class="cx">                                                         <key>interval</key>
</span><del>-                                                        <integer>60</integer>
</del><ins>+                                                        <integer>120</integer>
</ins><span class="cx">
</span><span class="cx">                                                         <!-- Define how start times (DTSTART) for the randomly generated events
</span><span class="cx">                                                                 will be selected. This is an example of a "Distribution" parameter. The value
</span><span class="lines">@@ -172,23 +172,30 @@
</span><span class="cx">
</span><span class="cx">                                         <!-- This profile will create a new event, and then periodically update the ACKNOWLEDGED property. -->
</span><span class="cx">
</span><del>-                                        <!-- Rather than use EventUpdater which always updates the same event,
-                                        you can use Eventer to create events and TitleChanger or Attacher to change
-                                        random events -->
</del><span class="cx">                                         <dict>
</span><span class="cx">                                                 <key>class</key>
</span><del>-                                                <string>contrib.performance.loadtest.profiles.EventUpdater</string>
</del><ins>+                                                <string>contrib.performance.loadtest.profiles.AlarmAcknowledger</string>
</ins><span class="cx">
</span><span class="cx">                                                 <key>params</key>
</span><span class="cx">                                                 <dict>
</span><span class="cx">                                                         <key>enabled</key>
</span><del>-                                                        <false/>
</del><ins>+                                                        <true/>
</ins><span class="cx">
</span><del>-                                                        <!-- Define the interval (in seconds) at which this profile will use
-                                                                its client to create a new event. -->
</del><ins>+                                                        <!-- Define how often to check (in seconds) whether it's
+                                                        time to do an alarm acknowledgement -->
</ins><span class="cx">                                                         <key>interval</key>
</span><del>-                                                        <integer>5</integer>
</del><ins>+                                                        <integer>15</integer>
</ins><span class="cx">
</span><ins>+                                                        <!-- Acknowledgements will only actually occur at one of these
+                                                        minutes past the hour: -->
+                                                        <key>pastTheHour</key>
+                                                        <array>
+                                                                <integer>0</integer>
+                                                                <integer>15</integer>
+                                                                <integer>30</integer>
+                                                                <integer>45</integer>
+                                                        </array>
+
</ins><span class="cx">                                                         <!-- Define how start times (DTSTART) for the randomly generated events
</span><span class="cx">                                                                 will be selected. This is an example of a "Distribution" parameter. The value
</span><span class="cx">                                                                 for most "Distribution" parameters are interchangeable and extensible. -->
</span><span class="lines">@@ -290,7 +297,7 @@
</span><span class="cx">                                                         <!-- Define the interval (in seconds) at which this profile will use
</span><span class="cx">                                                                 its client to create a new event. -->
</span><span class="cx">                                                         <key>interval</key>
</span><del>-                                                        <integer>60</integer>
</del><ins>+                                                        <integer>120</integer>
</ins><span class="cx">
</span><span class="cx">                                                 </dict>
</span><span class="cx">                                         </dict>
</span><span class="lines">@@ -308,7 +315,7 @@
</span><span class="cx">                                                         <!-- Define the interval (in seconds) at which this profile will use
</span><span class="cx">                                                                 its client to create a new event. -->
</span><span class="cx">                                                         <key>interval</key>
</span><del>-                                                        <integer>60</integer>
</del><ins>+                                                        <integer>120</integer>
</ins><span class="cx">
</span><span class="cx">                                                         <!-- Define the attachment size distribution. -->
</span><span class="cx">                                                         <key>fileSizeDistribution</key>
</span><span class="lines">@@ -373,12 +380,12 @@
</span><span class="cx">                                         <!-- This profile invites some number of new attendees to new events. -->
</span><span class="cx">                                         <dict>
</span><span class="cx">                                                 <key>class</key>
</span><del>-                                                <string>contrib.performance.loadtest.profiles.RealisticInviter</string>
</del><ins>+                                                <string>contrib.performance.loadtest.profiles.Inviter</string>
</ins><span class="cx">
</span><span class="cx">                                                 <key>params</key>
</span><span class="cx">                                                 <dict>
</span><span class="cx">                                                         <key>enabled</key>
</span><del>-                                                        <false/>
</del><ins>+                                                        <true/>
</ins><span class="cx">
</span><span class="cx">                                                         <!-- Define the frequency at which new invitations will be sent out. -->
</span><span class="cx">                                                         <key>sendInvitationDistribution</key>
</span><span class="lines">@@ -389,7 +396,7 @@
</span><span class="cx">                                                                 <dict>
</span><span class="cx">                                                                         <!-- mu gives the mean of the normal distribution (in seconds). -->
</span><span class="cx">                                                                         <key>mu</key>
</span><del>-                                                                        <integer>10</integer>
</del><ins>+                                                                        <integer>120</integer>
</ins><span class="cx">
</span><span class="cx">                                                                         <!-- and sigma gives its standard deviation. -->
</span><span class="cx">                                                                         <key>sigma</key>
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestprofilespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py (15299 => 15300)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2015-11-07 04:54:31 UTC (rev 15299)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2015-11-10 00:00:49 UTC (rev 15300)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> from twisted.python import context
</span><span class="cx"> from twisted.python.log import msg
</span><span class="cx"> from twisted.python.failure import Failure
</span><del>-from twisted.internet.defer import Deferred, succeed, fail, inlineCallbacks, returnValue
</del><ins>+from twisted.internet.defer import Deferred, succeed, inlineCallbacks, returnValue
</ins><span class="cx"> from twisted.internet.task import LoopingCall
</span><span class="cx"> from twisted.web.http import PRECONDITION_FAILED
</span><span class="cx">
</span><span class="lines">@@ -45,6 +45,8 @@
</span><span class="cx"> from pycalendar.datetime import DateTime
</span><span class="cx"> from pycalendar.duration import Duration
</span><span class="cx">
</span><ins>+from datetime import datetime
+
</ins><span class="cx"> class ProfileBase(object):
</span><span class="cx"> """
</span><span class="cx"> Base class which provides some conveniences for profile
</span><span class="lines">@@ -114,6 +116,9 @@
</span><span class="cx"> event = calendar.events[href]
</span><span class="cx"> if not event.component:
</span><span class="cx"> continue
</span><ins>+ if event.scheduleTag:
+ continue
+
</ins><span class="cx"> return event
</span><span class="cx"> return None
</span><span class="cx">
</span><span class="lines">@@ -213,125 +218,9 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class Inviter(ProfileBase):
</span><span class="cx"> """
</span><del>- A Calendar user who invites and de-invites other users to events.
- """
- def setParameters(
- self,
- enabled=True,
- sendInvitationDistribution=NormalDistribution(600, 60),
- inviteeDistribution=UniformDiscreteDistribution(range(-10, 11))
- ):
- self.enabled = enabled
- self._sendInvitationDistribution = sendInvitationDistribution
- self._inviteeDistribution = inviteeDistribution
-
-
- def run(self):
- return loopWithDistribution(
- self._reactor, self._sendInvitationDistribution, self._invite)
-
-
- def _addAttendee(self, event, attendees):
- """
- Create a new attendee to add to the list of attendees for the
- given event.
- """
- selfRecord = self._sim.getUserRecord(self._number)
- invitees = set([u'mailto:%s' % (selfRecord.email,)])
- for att in attendees:
- invitees.add(att.value())
-
- for _ignore_i in range(10):
- invitee = max(
- 0, self._number + self._inviteeDistribution.sample())
- try:
- record = self._sim.getUserRecord(invitee)
- except IndexError:
- continue
- cuaddr = u'mailto:%s' % (record.email,)
- uuidx = u'urn:x-uid:%s' % (record.guid,)
- uuid = u'urn:uuid:%s' % (record.guid,)
- if cuaddr not in invitees and uuidx 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=cuaddr.encode("utf-8"),
- params={
- 'CN': record.commonName,
- 'CUTYPE': 'INDIVIDUAL',
- 'PARTSTAT': 'NEEDS-ACTION',
- 'ROLE': 'REQ-PARTICIPANT',
- 'RSVP': 'TRUE',
- },
- )
-
- return succeed(attendee)
-
-
- def _invite(self):
- """
- Try to add a new attendee to an event, or perhaps remove an
- existing attendee from an event.
-
- @return: C{None} if there are no events to play with,
- otherwise a L{Deferred} which fires when the attendee
- change has been made.
- """
-
- if not self._client.started:
- return succeed(None)
-
- # Find calendars which are eligible for invites
- calendars = self._calendarsOfType(caldavxml.calendar, "VEVENT")
-
- while calendars:
- # Pick one at random from which to try to select an event
- # to modify.
- calendar = self.random.choice(calendars)
- calendars.remove(calendar)
-
- if not calendar.events:
- continue
-
- events = calendar.events.keys()
- while events:
- uuid = self.random.choice(events)
- events.remove(uuid)
- event = calendar.events[uuid].component
- if event is None:
- continue
-
- component = event.mainComponent()
- organizer = component.getOrganizerProperty()
- if organizer is not None and not self._isSelfAttendee(organizer):
- # This event was organized by someone else, don't try to invite someone to it.
- continue
-
- href = calendar.url + uuid
-
- # Find out who might attend
- attendees = tuple(component.properties('ATTENDEE'))
-
- d = self._addAttendee(event, attendees)
- d.addCallbacks(
- lambda attendee:
- self._client.addEventAttendee(
- href, attendee),
- lambda reason: reason.trap(CannotAddAttendee))
- return self._newOperation("invite", d)
-
- # Oops, either no events or no calendars to play with.
- return succeed(None)
-
-
-
-class RealisticInviter(ProfileBase):
- """
</del><span class="cx"> A Calendar user who invites other users to new events.
</span><span class="cx"> """
</span><span class="cx"> _eventTemplate = Component.fromString("""\
</span><span class="lines">@@ -473,8 +362,7 @@
</span><span class="cx"> try:
</span><span class="cx"> self._addAttendee(vevent, attendees)
</span><span class="cx"> except CannotAddAttendee:
</span><del>- self._failedOperation("invite", "Cannot add attendee")
- return succeed(None)
</del><ins>+ continue
</ins><span class="cx">
</span><span class="cx"> href = '%s%s.ics' % (calendar.url, uid)
</span><span class="cx"> d = self._client.addInvite(href, vcalendar)
</span><span class="lines">@@ -868,10 +756,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-# Is the purpose of this profile "EventUpdater" simply to keep updating the same
-# resource over and over?
-
-class EventUpdater(ProfileBase):
</del><ins>+class AlarmAcknowledger(ProfileBase):
</ins><span class="cx"> """
</span><span class="cx"> A Calendar user who creates a new event, and then updates its alarm.
</span><span class="cx"> """
</span><span class="lines">@@ -903,7 +788,8 @@
</span><span class="cx"> def setParameters(
</span><span class="cx"> self,
</span><span class="cx"> enabled=True,
</span><del>- interval=25,
</del><ins>+ interval=5,
+ pastTheHour=[0, 15, 30, 45],
</ins><span class="cx"> eventStartDistribution=NearFutureDistribution(),
</span><span class="cx"> eventDurationDistribution=UniformDiscreteDistribution([
</span><span class="cx"> 15 * 60, 30 * 60,
</span><span class="lines">@@ -914,9 +800,11 @@
</span><span class="cx"> ):
</span><span class="cx"> self.enabled = enabled
</span><span class="cx"> self._interval = interval
</span><ins>+ self._pastTheHour = pastTheHour
</ins><span class="cx"> self._eventStartDistribution = eventStartDistribution
</span><span class="cx"> self._eventDurationDistribution = eventDurationDistribution
</span><span class="cx"> self._recurrenceDistribution = recurrenceDistribution
</span><ins>+ self._lastMinuteChecked = -1
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def initialize(self):
</span><span class="lines">@@ -925,6 +813,7 @@
</span><span class="cx">
</span><span class="cx"> @return: a L{Deferred} that fires when initialization is done
</span><span class="cx"> """
</span><ins>+
</ins><span class="cx"> return self._initEvent()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -968,16 +857,35 @@
</span><span class="cx"> return self._newOperation("create", d)
</span><span class="cx">
</span><span class="cx">
</span><ins>+ def _shouldUpdate(self, minutePastTheHour):
+ """
+ We want to only acknowledge our alarm at the "past the hour" minutes
+ we've been configured for.
+ """
+ should = False
+ if minutePastTheHour in self._pastTheHour:
+ # This is one of the minutes we should update on, but only update
+ # as we pass into this minute, and not subsequent times
+ if minutePastTheHour != self._lastMinuteChecked:
+ should = True
+
+ self._lastMinuteChecked = minutePastTheHour
+ return should
+
+
</ins><span class="cx"> def _updateEvent(self):
</span><span class="cx"> """
</span><del>- Try to add a new attendee to an event, or perhaps remove an
- existing attendee from an event.
</del><ins>+ Set the ACKNOWLEDGED property on an event.
</ins><span class="cx">
</span><span class="cx"> @return: C{None} if there are no events to play with,
</span><del>- otherwise a L{Deferred} which fires when the attendee
</del><ins>+ otherwise a L{Deferred} which fires when the acknowledged
</ins><span class="cx"> change has been made.
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+ # Only do updates when we reach of the designated minutes past the hour
+ if not self._shouldUpdate(datetime.now().minute):
+ return succeed(None)
+
</ins><span class="cx"> if not self._client.started:
</span><span class="cx"> return succeed(None)
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtesttest_profilespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py (15299 => 15300)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py        2015-11-07 04:54:31 UTC (rev 15299)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py        2015-11-10 00:00:49 UTC (rev 15300)
</span><span class="lines">@@ -31,8 +31,7 @@
</span><span class="cx">
</span><span class="cx"> from twistedcaldav.ical import Component, Property
</span><span class="cx">
</span><del>-from contrib.performance.loadtest.profiles import Eventer, Inviter, Accepter, OperationLogger
-from contrib.performance.loadtest.profiles import RealisticInviter
</del><ins>+from contrib.performance.loadtest.profiles import Eventer, Inviter, Accepter, OperationLogger, AlarmAcknowledger
</ins><span class="cx"> from contrib.performance.loadtest.population import Populator, CalendarClientSimulator
</span><span class="cx"> from contrib.performance.loadtest.ical import IncorrectResponseCode, Calendar, Event, BaseClient
</span><span class="cx"> from contrib.performance.loadtest.sim import _DirectoryRecord
</span><span class="lines">@@ -340,209 +339,212 @@
</span><span class="cx"> return self.values.pop(0)
</span><span class="cx">
</span><span class="cx">
</span><ins>+# These were for the old Inviter class, before RealisticInviter was renamed
+# to Inviter. Keeping them around in case there are some we want to copy
+# over to the new Inviter:
+#
+# class InviterTests(TestCase):
+# """
+# Tests for loadtest.profiles.Inviter.
+# """
+# def setUp(self):
+# self.sim = CalendarClientSimulator(
+# AnyUser(), Populator(None), None, None, None, None, None, None)
</ins><span class="cx">
</span><del>-class InviterTests(TestCase):
- """
- Tests for loadtest.profiles.Inviter.
- """
- def setUp(self):
- self.sim = CalendarClientSimulator(
- AnyUser(), Populator(None), None, None, None, None, None, None)
</del><span class="cx">
</span><ins>+# def _simpleAccount(self, userNumber, eventText):
+# client = StubClient(userNumber, self.mktemp())
</ins><span class="cx">
</span><del>- def _simpleAccount(self, userNumber, eventText):
- client = StubClient(userNumber, self.mktemp())
</del><ins>+# vevent = Component.fromString(eventText)
+# calendar = Calendar(
+# caldavxml.calendar, set(('VEVENT',)), u'calendar', u'/cal/', None)
+# client._calendars.update({calendar.url: calendar})
</ins><span class="cx">
</span><del>- vevent = Component.fromString(eventText)
- calendar = Calendar(
- caldavxml.calendar, set(('VEVENT',)), u'calendar', u'/cal/', None)
- client._calendars.update({calendar.url: calendar})
</del><ins>+# event = Event(client.serializeLocation(), calendar.url + u'1234.ics', None, vevent)
</ins><span class="cx">
</span><del>- event = Event(client.serializeLocation(), calendar.url + u'1234.ics', None, vevent)
</del><ins>+# client._events.update({event.url: event})
+# calendar.events = {u'1234.ics': event}
</ins><span class="cx">
</span><del>- client._events.update({event.url: event})
- calendar.events = {u'1234.ics': event}
</del><ins>+# return vevent, event, calendar, client
</ins><span class="cx">
</span><del>- return vevent, event, calendar, client
</del><span class="cx">
</span><ins>+# def test_enabled(self):
+# userNumber = 13
+# client = StubClient(userNumber, self.mktemp())
</ins><span class="cx">
</span><del>- def test_enabled(self):
- userNumber = 13
- client = StubClient(userNumber, self.mktemp())
</del><ins>+# inviter = Inviter(None, self.sim, client, userNumber, **{"enabled": False})
+# self.assertEqual(inviter.enabled, False)
</ins><span class="cx">
</span><del>- inviter = Inviter(None, self.sim, client, userNumber, **{"enabled": False})
- self.assertEqual(inviter.enabled, False)
</del><ins>+# inviter = Inviter(None, self.sim, client, userNumber, **{"enabled": True})
+# self.assertEqual(inviter.enabled, True)
</ins><span class="cx">
</span><del>- inviter = Inviter(None, self.sim, client, userNumber, **{"enabled": True})
- self.assertEqual(inviter.enabled, True)
</del><span class="cx">
</span><ins>+# def test_doNotAddAttendeeToInbox(self):
+# """
+# When the only calendar with any events is a schedule inbox, no
+# attempt is made to add attendees to an event on that calendar.
+# """
+# userNumber = 10
+# vevent, _ignore_event, calendar, client = self._simpleAccount(
+# userNumber, SIMPLE_EVENT)
+# calendar.resourceType = caldavxml.schedule_inbox
+# inviter = Inviter(None, self.sim, client, userNumber)
+# inviter._invite()
+# self.assertFalse(vevent.mainComponent().hasProperty('ATTENDEE'))
</ins><span class="cx">
</span><del>- def test_doNotAddAttendeeToInbox(self):
- """
- When the only calendar with any events is a schedule inbox, no
- attempt is made to add attendees to an event on that calendar.
- """
- userNumber = 10
- vevent, _ignore_event, calendar, client = self._simpleAccount(
- userNumber, SIMPLE_EVENT)
- calendar.resourceType = caldavxml.schedule_inbox
- inviter = Inviter(None, self.sim, client, userNumber)
- inviter._invite()
- self.assertFalse(vevent.mainComponent().hasProperty('ATTENDEE'))
</del><span class="cx">
</span><ins>+# def test_doNotAddAttendeeToNoCalendars(self):
+# """
+# When there are no calendars and no events at all, the inviter
+# does nothing.
+# """
+# userNumber = 13
+# client = StubClient(userNumber, self.mktemp())
+# inviter = Inviter(None, self.sim, client, userNumber)
+# inviter._invite()
+# self.assertEquals(client._events, {})
+# self.assertEquals(client._calendars, {})
</ins><span class="cx">
</span><del>- def test_doNotAddAttendeeToNoCalendars(self):
- """
- When there are no calendars and no events at all, the inviter
- does nothing.
- """
- userNumber = 13
- client = StubClient(userNumber, self.mktemp())
- inviter = Inviter(None, self.sim, client, userNumber)
- inviter._invite()
- self.assertEquals(client._events, {})
- self.assertEquals(client._calendars, {})
</del><span class="cx">
</span><ins>+# def test_doNotAddAttendeeToUninitializedEvent(self):
+# """
+# When there is an L{Event} on a calendar but the details of the
+# event have not yet been retrieved, no attempt is made to add
+# invitees to that event.
+# """
+# userNumber = 19
+# _ignore_vevent, event, calendar, client = self._simpleAccount(
+# userNumber, SIMPLE_EVENT)
+# event.component = event.etag = event.scheduleTag = None
+# inviter = Inviter(None, self.sim, client, userNumber)
+# inviter._invite()
+# self.assertEquals(client._events, {event.url: event})
+# self.assertEquals(client._calendars, {calendar.url: calendar})
</ins><span class="cx">
</span><del>- def test_doNotAddAttendeeToUninitializedEvent(self):
- """
- When there is an L{Event} on a calendar but the details of the
- event have not yet been retrieved, no attempt is made to add
- invitees to that event.
- """
- userNumber = 19
- _ignore_vevent, event, calendar, client = self._simpleAccount(
- userNumber, SIMPLE_EVENT)
- event.component = event.etag = event.scheduleTag = None
- inviter = Inviter(None, self.sim, client, userNumber)
- inviter._invite()
- self.assertEquals(client._events, {event.url: event})
- self.assertEquals(client._calendars, {calendar.url: calendar})
</del><span class="cx">
</span><ins>+# def test_addAttendeeToEvent(self):
+# """
+# When there is a normal calendar with an event, inviter adds an
+# attendee to it.
+# """
+# userNumber = 16
+# _ignore_vevent, event, _ignore_calendar, client = self._simpleAccount(
+# userNumber, SIMPLE_EVENT)
+# inviter = Inviter(Clock(), self.sim, client, userNumber)
+# inviter.setParameters(inviteeDistribution=Deterministic(1))
+# inviter._invite()
+# attendees = tuple(event.component.mainComponent().properties('ATTENDEE'))
+# self.assertEquals(len(attendees), 1)
+# for paramname, paramvalue in {
+# 'CN': 'User %d' % (userNumber + 1,),
+# 'CUTYPE': 'INDIVIDUAL',
+# 'PARTSTAT': 'NEEDS-ACTION',
+# 'ROLE': 'REQ-PARTICIPANT',
+# 'RSVP': 'TRUE'
+# }.items():
+# self.assertTrue(attendees[0].hasParameter(paramname))
+# self.assertEqual(attendees[0].parameterValue(paramname), paramvalue)
</ins><span class="cx">
</span><del>- def test_addAttendeeToEvent(self):
- """
- When there is a normal calendar with an event, inviter adds an
- attendee to it.
- """
- userNumber = 16
- _ignore_vevent, event, _ignore_calendar, client = self._simpleAccount(
- userNumber, SIMPLE_EVENT)
- inviter = Inviter(Clock(), self.sim, client, userNumber)
- inviter.setParameters(inviteeDistribution=Deterministic(1))
- inviter._invite()
- attendees = tuple(event.component.mainComponent().properties('ATTENDEE'))
- self.assertEquals(len(attendees), 1)
- for paramname, paramvalue in {
- 'CN': 'User %d' % (userNumber + 1,),
- 'CUTYPE': 'INDIVIDUAL',
- 'PARTSTAT': 'NEEDS-ACTION',
- 'ROLE': 'REQ-PARTICIPANT',
- 'RSVP': 'TRUE'
- }.items():
- self.assertTrue(attendees[0].hasParameter(paramname))
- self.assertEqual(attendees[0].parameterValue(paramname), paramvalue)
</del><span class="cx">
</span><ins>+# def test_doNotAddSelfToEvent(self):
+# """
+# If the inviter randomly selects its own user to be added to
+# the attendee list, a different user is added instead.
+# """
+# selfNumber = 12
+# _ignore_vevent, event, _ignore_calendar, client = self._simpleAccount(
+# selfNumber, SIMPLE_EVENT)
</ins><span class="cx">
</span><del>- def test_doNotAddSelfToEvent(self):
- """
- If the inviter randomly selects its own user to be added to
- the attendee list, a different user is added instead.
- """
- selfNumber = 12
- _ignore_vevent, event, _ignore_calendar, client = self._simpleAccount(
- selfNumber, SIMPLE_EVENT)
</del><ins>+# otherNumber = 20
+# values = [selfNumber - selfNumber, otherNumber - selfNumber]
</ins><span class="cx">
</span><del>- otherNumber = 20
- values = [selfNumber - selfNumber, otherNumber - selfNumber]
</del><ins>+# inviter = Inviter(Clock(), self.sim, client, selfNumber)
+# inviter.setParameters(inviteeDistribution=SequentialDistribution(values))
+# inviter._invite()
+# attendees = tuple(event.component.mainComponent().properties('ATTENDEE'))
+# self.assertEquals(len(attendees), 1)
+# for paramname, paramvalue in {
+# 'CN': 'User %d' % (otherNumber,),
+# 'CUTYPE': 'INDIVIDUAL',
+# 'PARTSTAT': 'NEEDS-ACTION',
+# 'ROLE': 'REQ-PARTICIPANT',
+# 'RSVP': 'TRUE'
+# }.items():
+# self.assertTrue(attendees[0].hasParameter(paramname))
+# self.assertEqual(attendees[0].parameterValue(paramname), paramvalue)
</ins><span class="cx">
</span><del>- inviter = Inviter(Clock(), self.sim, client, selfNumber)
- inviter.setParameters(inviteeDistribution=SequentialDistribution(values))
- inviter._invite()
- attendees = tuple(event.component.mainComponent().properties('ATTENDEE'))
- self.assertEquals(len(attendees), 1)
- for paramname, paramvalue in {
- 'CN': 'User %d' % (otherNumber,),
- 'CUTYPE': 'INDIVIDUAL',
- 'PARTSTAT': 'NEEDS-ACTION',
- 'ROLE': 'REQ-PARTICIPANT',
- 'RSVP': 'TRUE'
- }.items():
- self.assertTrue(attendees[0].hasParameter(paramname))
- self.assertEqual(attendees[0].parameterValue(paramname), paramvalue)
</del><span class="cx">
</span><ins>+# def test_doNotAddExistingToEvent(self):
+# """
+# If the inviter randomly selects a user which is already an
+# invitee on the event, a different user is added instead.
+# """
+# selfNumber = 1
+# _ignore_vevent, event, _ignore_calendar, client = self._simpleAccount(
+# selfNumber, INVITED_EVENT)
</ins><span class="cx">
</span><del>- def test_doNotAddExistingToEvent(self):
- """
- If the inviter randomly selects a user which is already an
- invitee on the event, a different user is added instead.
- """
- selfNumber = 1
- _ignore_vevent, event, _ignore_calendar, client = self._simpleAccount(
- selfNumber, INVITED_EVENT)
</del><ins>+# invitee = tuple(event.component.mainComponent().properties('ATTENDEE'))[0]
+# inviteeNumber = int(invitee.parameterValue('CN').split()[1])
+# anotherNumber = inviteeNumber + 5
+# values = [inviteeNumber - selfNumber, anotherNumber - selfNumber]
</ins><span class="cx">
</span><del>- invitee = tuple(event.component.mainComponent().properties('ATTENDEE'))[0]
- inviteeNumber = int(invitee.parameterValue('CN').split()[1])
- anotherNumber = inviteeNumber + 5
- values = [inviteeNumber - selfNumber, anotherNumber - selfNumber]
</del><ins>+# inviter = Inviter(Clock(), self.sim, client, selfNumber)
+# inviter.setParameters(inviteeDistribution=SequentialDistribution(values))
+# inviter._invite()
+# attendees = tuple(event.component.mainComponent().properties('ATTENDEE'))
+# self.assertEquals(len(attendees), 3)
+# for paramname, paramvalue in {
+# 'CN': 'User %02d' % (anotherNumber,),
+# 'CUTYPE': 'INDIVIDUAL',
+# 'PARTSTAT': 'NEEDS-ACTION',
+# 'ROLE': 'REQ-PARTICIPANT',
+# 'RSVP': 'TRUE'
+# }.items():
+# self.assertTrue(attendees[2].hasParameter(paramname))
+# self.assertEqual(attendees[2].parameterValue(paramname), paramvalue)
</ins><span class="cx">
</span><del>- inviter = Inviter(Clock(), self.sim, client, selfNumber)
- inviter.setParameters(inviteeDistribution=SequentialDistribution(values))
- inviter._invite()
- attendees = tuple(event.component.mainComponent().properties('ATTENDEE'))
- self.assertEquals(len(attendees), 3)
- for paramname, paramvalue in {
- 'CN': 'User %02d' % (anotherNumber,),
- 'CUTYPE': 'INDIVIDUAL',
- 'PARTSTAT': 'NEEDS-ACTION',
- 'ROLE': 'REQ-PARTICIPANT',
- 'RSVP': 'TRUE'
- }.items():
- self.assertTrue(attendees[2].hasParameter(paramname))
- self.assertEqual(attendees[2].parameterValue(paramname), paramvalue)
</del><span class="cx">
</span><ins>+# def test_everybodyInvitedAlready(self):
+# """
+# If the first so-many randomly selected users we come across
+# are already attendees on the event, the invitation attempt is
+# abandoned.
+# """
+# selfNumber = 1
+# vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
+# selfNumber, INVITED_EVENT)
+# inviter = Inviter(Clock(), self.sim, client, selfNumber)
+# # Always return a user number which has already been invited.
+# inviter.setParameters(inviteeDistribution=Deterministic(2 - selfNumber))
+# inviter._invite()
+# attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
+# self.assertEquals(len(attendees), 2)
</ins><span class="cx">
</span><del>- def test_everybodyInvitedAlready(self):
- """
- If the first so-many randomly selected users we come across
- are already attendees on the event, the invitation attempt is
- abandoned.
- """
- selfNumber = 1
- vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
- selfNumber, INVITED_EVENT)
- inviter = Inviter(Clock(), self.sim, client, selfNumber)
- # Always return a user number which has already been invited.
- inviter.setParameters(inviteeDistribution=Deterministic(2 - selfNumber))
- inviter._invite()
- attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
- self.assertEquals(len(attendees), 2)
</del><span class="cx">
</span><ins>+# def test_doNotInviteToSomeoneElsesEvent(self):
+# """
+# If there are events on our calendar which are being organized
+# by someone else, the inviter does not attempt to invite new
+# users to them.
+# """
+# selfNumber = 2
+# vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
+# selfNumber, INVITED_EVENT)
+# inviter = Inviter(None, self.sim, client, selfNumber)
+# # Try to send an invitation, but with only one event on the
+# # calendar, of which we are not the organizer. It should be
+# # unchanged afterwards.
+# inviter._invite()
+# attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
+# self.assertEqual(len(attendees), 2)
+# self.assertEqual(attendees[0].parameterValue('CN'), 'User 01')
+# self.assertEqual(attendees[1].parameterValue('CN'), 'User 02')
</ins><span class="cx">
</span><del>- def test_doNotInviteToSomeoneElsesEvent(self):
- """
- If there are events on our calendar which are being organized
- by someone else, the inviter does not attempt to invite new
- users to them.
- """
- selfNumber = 2
- vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
- selfNumber, INVITED_EVENT)
- inviter = Inviter(None, self.sim, client, selfNumber)
- # Try to send an invitation, but with only one event on the
- # calendar, of which we are not the organizer. It should be
- # unchanged afterwards.
- inviter._invite()
- attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
- self.assertEqual(len(attendees), 2)
- self.assertEqual(attendees[0].parameterValue('CN'), 'User 01')
- self.assertEqual(attendees[1].parameterValue('CN'), 'User 02')
</del><span class="cx">
</span><span class="cx">
</span><del>-
-class RealisticInviterTests(TestCase):
</del><ins>+class InviterTests(TestCase):
</ins><span class="cx"> """
</span><del>- Tests for loadtest.profiles.RealisticInviter.
</del><ins>+ Tests for loadtest.profiles.Inviter.
</ins><span class="cx"> """
</span><span class="cx"> def setUp(self):
</span><span class="cx"> self.sim = CalendarClientSimulator(
</span><span class="lines">@@ -566,10 +568,10 @@
</span><span class="cx"> userNumber = 13
</span><span class="cx"> client = StubClient(userNumber, self.mktemp())
</span><span class="cx">
</span><del>- inviter = RealisticInviter(None, self.sim, client, userNumber, **{"enabled": False})
</del><ins>+ inviter = Inviter(None, self.sim, client, userNumber, **{"enabled": False})
</ins><span class="cx"> self.assertEqual(inviter.enabled, False)
</span><span class="cx">
</span><del>- inviter = RealisticInviter(None, self.sim, client, userNumber, **{"enabled": True})
</del><ins>+ inviter = Inviter(None, self.sim, client, userNumber, **{"enabled": True})
</ins><span class="cx"> self.assertEqual(inviter.enabled, True)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -584,7 +586,7 @@
</span><span class="cx"> client = StubClient(userNumber, self.mktemp())
</span><span class="cx"> client._calendars.update({calendar.url: calendar})
</span><span class="cx">
</span><del>- inviter = RealisticInviter(None, self.sim, client, userNumber, **{"enabled": False})
</del><ins>+ inviter = Inviter(None, self.sim, client, userNumber, **{"enabled": False})
</ins><span class="cx"> inviter._invite()
</span><span class="cx">
</span><span class="cx"> self.assertEquals(client._events, {})
</span><span class="lines">@@ -597,7 +599,7 @@
</span><span class="cx"> """
</span><span class="cx"> userNumber = 13
</span><span class="cx"> client = StubClient(userNumber, self.mktemp())
</span><del>- inviter = RealisticInviter(None, self.sim, client, userNumber)
</del><ins>+ inviter = Inviter(None, self.sim, client, userNumber)
</ins><span class="cx"> inviter._invite()
</span><span class="cx"> self.assertEquals(client._events, {})
</span><span class="cx"> self.assertEquals(client._calendars, {})
</span><span class="lines">@@ -614,7 +616,7 @@
</span><span class="cx"> os.mkdir(serializePath)
</span><span class="cx"> client = StubClient(userNumber, self.mktemp())
</span><span class="cx"> client._calendars.update({calendar.url: calendar})
</span><del>- inviter = RealisticInviter(Clock(), self.sim, client, userNumber)
</del><ins>+ inviter = Inviter(Clock(), self.sim, client, userNumber)
</ins><span class="cx"> inviter.setParameters(
</span><span class="cx"> inviteeDistribution=Deterministic(1),
</span><span class="cx"> inviteeCountDistribution=Deterministic(1)
</span><span class="lines">@@ -642,7 +644,7 @@
</span><span class="cx"> otherNumber = 20
</span><span class="cx"> values = [selfNumber - selfNumber, otherNumber - selfNumber]
</span><span class="cx">
</span><del>- inviter = RealisticInviter(Clock(), self.sim, client, selfNumber)
</del><ins>+ inviter = Inviter(Clock(), self.sim, client, selfNumber)
</ins><span class="cx"> inviter.setParameters(
</span><span class="cx"> inviteeDistribution=SequentialDistribution(values),
</span><span class="cx"> inviteeCountDistribution=Deterministic(1)
</span><span class="lines">@@ -671,7 +673,7 @@
</span><span class="cx"> anotherNumber = inviteeNumber + 5
</span><span class="cx"> values = [inviteeNumber - selfNumber, inviteeNumber - selfNumber, anotherNumber - selfNumber]
</span><span class="cx">
</span><del>- inviter = RealisticInviter(Clock(), self.sim, client, selfNumber)
</del><ins>+ inviter = Inviter(Clock(), self.sim, client, selfNumber)
</ins><span class="cx"> inviter.setParameters(
</span><span class="cx"> inviteeDistribution=SequentialDistribution(values),
</span><span class="cx"> inviteeCountDistribution=Deterministic(2)
</span><span class="lines">@@ -700,7 +702,7 @@
</span><span class="cx"> userNumber = 1
</span><span class="cx"> client = StubClient(userNumber, self.mktemp())
</span><span class="cx"> client._calendars.update({calendar.url: calendar})
</span><del>- inviter = RealisticInviter(Clock(), self.sim, client, userNumber)
</del><ins>+ inviter = Inviter(Clock(), self.sim, client, userNumber)
</ins><span class="cx"> inviter.setParameters(
</span><span class="cx"> inviteeDistribution=Deterministic(1),
</span><span class="cx"> inviteeCountDistribution=Deterministic(2)
</span><span class="lines">@@ -1089,3 +1091,22 @@
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> ["Greater than 1% TESTING failed"],
</span><span class="cx"> logger.failures())
</span><ins>+
+
+class AlarmAcknowledgerTests(TestCase):
+
+ def test_pastTheHour(self):
+ acknowledger = AlarmAcknowledger(None, None, None, {})
+ self.assertTrue(acknowledger._shouldUpdate(0))
+ self.assertFalse(acknowledger._shouldUpdate(0))
+ self.assertFalse(acknowledger._shouldUpdate(1))
+ self.assertFalse(acknowledger._shouldUpdate(1))
+ self.assertFalse(acknowledger._shouldUpdate(14))
+ self.assertTrue(acknowledger._shouldUpdate(15))
+ self.assertFalse(acknowledger._shouldUpdate(15))
+ self.assertFalse(acknowledger._shouldUpdate(16))
+ self.assertTrue(acknowledger._shouldUpdate(30))
+ self.assertFalse(acknowledger._shouldUpdate(30))
+ self.assertFalse(acknowledger._shouldUpdate(59))
+ self.assertTrue(acknowledger._shouldUpdate(0))
+ self.assertFalse(acknowledger._shouldUpdate(0))
</ins></span></pre>
</div>
</div>
</body>
</html>