<!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>[15051] CalendarServer/branches/users/sredmond/clientsim/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/15051">15051</a></dd>
<dt>Author</dt> <dd>sredmond@apple.com</dd>
<dt>Date</dt> <dd>2015-08-18 11:04:26 -0700 (Tue, 18 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>More unit tests</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestdistributionspy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/distributions.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtesticalpy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/ical.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestprofilespy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/profiles.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestpushpy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/push.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestrequesterpy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/requester.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtesttemplatespy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/templates.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_distributionspy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_distributions.py</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestpubsubpy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/pubsub.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_pubsubpy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_pubsub.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_pushpy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_push.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_requesterpy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_requester.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_resourcespy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_resources.py</a></li>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_templatespy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_templates.py</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestsubscribepy">CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/subscribe.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestdistributionspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/distributions.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/distributions.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/distributions.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -20,12 +20,12 @@
</span><span class="cx"> Base statistical functions
</span><span class="cx">   mean / median / stddev / mad / residuals
</span><span class="cx"> 
</span><del>-IPopulation interface exposes:
</del><ins>+IDistribution interface exposes:
</ins><span class="cx">   sample()
</span><span class="cx"> 
</span><span class="cx"> Sampling from this distribution must *not* change the underlying behavior of a distribution
</span><span class="cx"> 
</span><del>-Distributions (all of which implement IPopulation):
</del><ins>+Distributions (all of which implement IDistribution):
</ins><span class="cx">   UniformDiscreteDistribution
</span><span class="cx">   LogNormalDistribution
</span><span class="cx">   FixedDistribution
</span><span class="lines">@@ -49,17 +49,19 @@
</span><span class="cx"> from twisted.python.util import FancyEqMixin
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-class IPopulation(Interface):
</del><ins>+class IDistribution(Interface):
</ins><span class="cx">     &quot;&quot;&quot;Interface for a class that provides a single function, `sample`, which returns a float&quot;&quot;&quot;
</span><span class="cx">     def sample(): #@NoSelf
</span><span class="cx">         pass
</span><span class="cx"> 
</span><ins>+class Bounded
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class UniformDiscreteDistribution(object, FancyEqMixin):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    implements(IPopulation)
</del><ins>+    implements(IDistribution)
</ins><span class="cx"> 
</span><span class="cx">     compareAttributes = ['_values']
</span><span class="cx"> 
</span><span class="lines">@@ -85,7 +87,7 @@
</span><span class="cx"> class LogNormalDistribution(object, FancyEqMixin):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    implements(IPopulation)
</del><ins>+    implements(IDistribution)
</ins><span class="cx"> 
</span><span class="cx">     compareAttributes = ['_mu', '_sigma', '_maximum']
</span><span class="cx"> 
</span><span class="lines">@@ -134,7 +136,7 @@
</span><span class="cx"> class FixedDistribution(object, FancyEqMixin):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    implements(IPopulation)
</del><ins>+    implements(IDistribution)
</ins><span class="cx"> 
</span><span class="cx">     compareAttributes = ['_value']
</span><span class="cx"> 
</span><span class="lines">@@ -395,30 +397,16 @@
</span><span class="cx"> 
</span><span class="cx">         return None
</span><span class="cx"> 
</span><del>-class HappyFaceStartDistribution(object, FancyEqMixin):
-    compareAttributes = []
-    def __init__(self, scale):
-        self._scale = scale
-
-    def sample(self):
-        return nprandom.exponential(self._scale)
-
-class HappyFaceDurationDistribution(object, FancyEqMixin):
-    compareAttributes = []
-    def __init__(self):
-        self._distribution = UniformDiscreteDistribution(60 * 15, 60 * 30)
-
-    def sample(self):
-        return self._distribution.sample()
-
-
</del><span class="cx"> if __name__ == '__main__':
</span><span class="cx">     from collections import defaultdict
</span><del>-    mu = 1.5
-    sigma = 1.22
</del><ins>+    mu = 15
+    sigma = 12
+    print(&quot;Testing LogNormalDistribution with mu={mu}, sigma={sigma}&quot;.format(
+        mu=mu, sigma=sigma
+    ))
</ins><span class="cx">     distribution = LogNormalDistribution(mu, sigma, 100)
</span><span class="cx">     result = defaultdict(int)
</span><del>-    for i in range(100000):
</del><ins>+    for _ignore_i in xrange(100000):
</ins><span class="cx">         s = int(distribution.sample())
</span><span class="cx">         if s &gt; 300:
</span><span class="cx">             continue
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtesticalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/ical.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/ical.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/ical.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx"> from caldavclientlibrary.protocol.url import URL
</span><span class="cx"> 
</span><span class="cx"> from contrib.performance.httpclient import readBody
</span><del>-from contrib.performance.loadtest.subscribe import Periodical
</del><ins>+from contrib.performance.loadtest.pubsub import Publisher
</ins><span class="cx"> from contrib.performance.loadtest.resources import Event, Calendar
</span><span class="cx"> from contrib.performance.loadtest.requester import Requester, IncorrectResponseCode
</span><span class="cx"> from contrib.performance.loadtest.push import PushMonitor
</span><span class="lines">@@ -293,7 +293,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Allow events to go out into the world.
</span><span class="cx">         self.catalog = {
</span><del>-            &quot;eventChanged&quot;: Periodical(),
</del><ins>+            &quot;eventChanged&quot;: Publisher(),
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         self._checking = set()
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestprofilespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/profiles.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/profiles.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/profiles.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -864,10 +864,7 @@
</span><span class="cx">     PRIORITY_LOW = 9
</span><span class="cx"> 
</span><span class="cx">     def _setPriority(self, priority, vtodo):
</span><del>-        if priority == self.PRIORITY_NONE:
-            vtodo.removeProperty(&quot;PRIORITY&quot;)
-        else:
-            vtodo.replaceProperty(Property(&quot;PRIORITY&quot;, priority))
</del><ins>+        vtodo.replaceProperty(Property(&quot;PRIORITY&quot;, priority))
</ins><span class="cx"> 
</span><span class="cx"> class Completer(TaskBase):
</span><span class="cx">     def _markTaskComplete(vtodo):
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestpubsubpy"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/pubsub.py (0 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/pubsub.py                                (rev 0)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/pubsub.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+##
+# Copyright (c) 2011-2015 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# 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 &quot;AS IS&quot; 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.
+#
+##
+&quot;&quot;&quot;
+Publisher-Subscription model
+&quot;&quot;&quot;
+class _Subscription(object):
+    def __init__(self, publisher, subscriber):
+        self.publisher = publisher
+        self.subscriber = subscriber
+
+
+    def cancel(self):
+        self.publisher.subscriptions.remove(self)
+
+
+    def issue(self, issue):
+        self.subscriber(issue)
+
+
+
+class Publisher(object):
+    def __init__(self):
+        self.subscriptions = []
+
+
+    def subscribe(self, who):
+        subscription = _Subscription(self, who)
+        self.subscriptions.append(subscription)
+        return subscription
+
+
+    def issue(self, issue):
+        for subscr in self.subscriptions:
+            subscr.issue(issue)
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestpushpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/push.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/push.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/push.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -3,8 +3,7 @@
</span><span class="cx"> 
</span><span class="cx"> class PushMonitor(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Representation of a watchguard that monitors
-    push notifications (AMP Push)
</del><ins>+    Watchguard that monitors push notifications (AMP Push)
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     def __init__(
</span><span class="lines">@@ -15,11 +14,16 @@
</span><span class="cx">         callback
</span><span class="cx">     ):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        reactor: Twisted reactor
-        ampPushHost: localhost
-        ampPushPort: 62311
-        callback: a one-argument function that is fired with a calendar href
-                  upon receipt of a push notification for that resource
</del><ins>+        @param reactor: Twisted reactor
+        @type reactor: twisted.web.reactor
+        @param ampPushHost: AMP host to connect to (e.g. 'localhost')
+        @type ampPushHost: string
+        @param ampPushPort: AMP port to connect to (e.g. 62311)
+        @type ampPushPort: integer
+        @param callback: a one-argument function that is fired
+            with a calendar hrefupon receipt of a push notification
+            for that resource
+        @type callback: one-argument callable
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         self.reactor = reactor
</span><span class="cx">         self.ampPushHost = ampPushHost
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestrequesterpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/requester.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/requester.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/requester.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -293,7 +293,10 @@
</span><span class="cx">         self.expected = expected
</span><span class="cx">         self.response = response
</span><span class="cx"> 
</span><ins>+    def __repr__(self):
+        return &quot;%s &quot;
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class WebClientContextFactory(ClientContextFactory):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     A web context factory which ignores the hostname and port and does no
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestsubscribepy"></a>
<div class="delfile"><h4>Deleted: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/subscribe.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/subscribe.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/subscribe.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -1,30 +0,0 @@
</span><del>-
-class Subscription(object):
-    def __init__(self, periodical, subscriber):
-        self.periodical = periodical
-        self.subscriber = subscriber
-
-
-    def cancel(self):
-        self.periodical.subscriptions.remove(self)
-
-
-    def issue(self, issue):
-        self.subscriber(issue)
-
-
-
-class Periodical(object):
-    def __init__(self):
-        self.subscriptions = []
-
-
-    def subscribe(self, who):
-        subscription = Subscription(self, who)
-        self.subscriptions.append(subscription)
-        return subscription
-
-
-    def issue(self, issue):
-        for subscr in self.subscriptions:
-            subscr.issue(issue)
</del></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtesttemplatespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/templates.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/templates.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/templates.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -21,16 +21,15 @@
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav.ical import Component
</span><span class="cx"> 
</span><del>-# Default event
-# Todo - decide on default timezone, also should we have X-ATAB?
-eventTemplate = Component.fromString(&quot;&quot;&quot;\
</del><ins>+_baseTemplate = Component.newCalendar()
+
+_veventTemplate = Component.fromString(&quot;&quot;&quot;\
</ins><span class="cx"> BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//Apple Inc.//Mac OS X 10.11//EN
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> TRANSP:OPAQUE
</span><del>-X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC
</del><span class="cx"> SUMMARY:Sample Event
</span><span class="cx"> UID:00000000-0000-0000-0000-000000000000
</span><span class="cx"> CREATED:00000000T000000Z
</span><span class="lines">@@ -42,6 +41,30 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</span><span class="cx"> 
</span><ins>+_valarmTemplate = Component.fromString(&quot;&quot;&quot;\
+BEGIN:VALARM
+X-WR-ALARMUID:00000000-0000-0000-0000-000000000000
+UID:00000000-0000-0000-0000-000000000000
+DESCRIPTION:Sample Alarm
+TRIGGER:-PT5M
+ACTION:DISPLAY
+END:VALARM
+&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
+
+_vtodoTemplate = Component.fromString(&quot;&quot;&quot;\
+BEGIN:VTODO
+SUMMARY:Sample Task
+UID:00000000-0000-0000-0000-000000000000
+CREATED:00000000T000000Z
+DTSTAMP:00000000T000000Z
+SEQUENCE:0
+END:VTODO
+&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
+
+# Default Event
+eventTemplate = _baseTemplate.duplicate()
+
+# Default Alarm
</ins><span class="cx"> alarmTemplate = Component.fromString(&quot;&quot;&quot;\
</span><span class="cx"> BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -55,8 +78,9 @@
</span><span class="cx"> ACTION:DISPLAY
</span><span class="cx"> END:VALARM
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</del><ins>+&quot;&quot;&quot;)
</ins><span class="cx"> 
</span><ins>+# Default task
</ins><span class="cx"> taskTemplate = Component.fromString(&quot;&quot;&quot;\
</span><span class="cx"> BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_distributionspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_distributions.py (15050 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_distributions.py        2015-08-17 21:24:30 UTC (rev 15050)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_distributions.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -8,7 +8,18 @@
</span><span class="cx"> from pycalendar.datetime import DateTime
</span><span class="cx"> from pycalendar.timezone import Timezone
</span><span class="cx"> 
</span><ins>+class DistributionTestBase(TestCase):
+    def getSamples(self, n):
+        samples = []
+        for _ignore_i in xrange(n):
+            samples.append()
+
+    def close(self, n):
+        pass
+
</ins><span class="cx"> class DistributionTests(TestCase):
</span><ins>+
+
</ins><span class="cx">     def test_lognormal(self):
</span><span class="cx">         dist = LogNormalDistribution(mu=1, sigma=1)
</span><span class="cx">         for _ignore_i in range(100):
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_pubsubpy"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_pubsub.py (0 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_pubsub.py                                (rev 0)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_pubsub.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -0,0 +1,86 @@
</span><ins>+##
+# Copyright (c) 2011-2015 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# 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 &quot;AS IS&quot; 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.
+#
+##
+&quot;&quot;&quot;
+Tests for loadtest.pubsub
+&quot;&quot;&quot;
+from collections import defaultdict
+
+from twisted.trial.unittest import TestCase
+
+from contrib.performance.loadtest.pubsub import Publisher
+
+
+class PubSubTests(TestCase):
+    &quot;&quot;&quot;Tests for Publisher&quot;&quot;&quot;
+    def setUp(self):
+        self.publisher = Publisher()
+        # Maps IDs of subscribers to values issued
+        self.values = defaultdict(list)
+
+
+    def recordValueWithID(self, id):
+        &quot;&quot;&quot;
+        Return a one-argument callable for use as a subscriber
+        that appends its argument to the list of values associated with id
+        &quot;&quot;&quot;
+        def recordValue(value):
+            self.values[id].append(value)
+        return recordValue
+
+
+    def test_noSubscribers(self):
+        &quot;&quot;&quot;When no subscriptions are present, no value is published&quot;&quot;&quot;
+        value = 'foobar'
+        self.publisher.issue(value)
+        self.assertEqual(self.values['sub1'], [])
+
+
+    def test_subscribe(self):
+        &quot;&quot;&quot;Published values propagate to their subscribers&quot;&quot;&quot;
+        value = 'foobar'
+        self.publisher.subscribe(self.recordValueWithID('sub1'))
+        self.publisher.issue(value)
+        self.assertEqual(self.values['sub1'], [value])
+
+
+    def test_cancel(self):
+        &quot;&quot;&quot;Cancelled subscriptions do not receive new publications&quot;&quot;&quot;
+        value = 'foobar'
+        subscr = self.publisher.subscribe(self.recordValueWithID('sub1'))
+        subscr.cancel()
+        self.publisher.issue(value)
+        self.assertEqual(self.values['sub1'], [])
+
+
+    def test_multiple_subscriptions(self):
+        &quot;&quot;&quot;Publisher supports adding and removing multiple subscriptions&quot;&quot;&quot;
+        value = 'foobar'
+        subscr1 = self.publisher.subscribe(self.recordValueWithID('sub1'))
+        subscr2 = self.publisher.subscribe(self.recordValueWithID('sub2'))
+        self.publisher.issue(value)
+        self.assertEqual(self.values['sub1'], [value])
+        self.assertEqual(self.values['sub2'], [value])
+
+        subscr2.cancel()
+        self.publisher.issue(value)
+        self.assertEqual(self.values['sub1'], [value, value])
+        self.assertEqual(self.values['sub2'], [value])
+
+        subscr1.cancel()
+        self.publisher.issue(value)
+        self.assertEqual(self.values['sub1'], [value, value])
+        self.assertEqual(self.values['sub2'], [value])
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_pushpy"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_push.py (0 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_push.py                                (rev 0)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_push.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+from twisted.trial.unittest import TestCase
+
+from calendarserver.push.amppush import AMPPushMaster
+
+from contrib.performance.loadtest.push import PushMonitor
+
+class PushMonitorTests(TestCase):
+    def receivedPush(self, href):
+        print href
+
+    def setUp(self):
+        self.pushMaster = AMPPushMaster()
+
+        self.monitor = PushMonitor(
+            None,
+            'localhost',
+            62311,
+            self.receivedPush
+        )
+
+    def sendNotification(self, href, pushkey):
+        self.pushMaster.notify(href, pushkey, None, None)
+
+    def test_addPushkey(self):
+        pass
+
+    def test_removePushkey(self):
+        pass
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_requesterpy"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_requester.py (0 => 15051)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_requester.py                                (rev 0)
+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_requester.py        2015-08-18 18:04:26 UTC (rev 15051)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+from twisted.trial.unittest import TestCase
+
+from contrib.performance.loadtest.requester import (
+    Requester, IncorrectResponseCode, WebClientContextFactory
+)
+
+class _FakeAgent(object):
+    def __init__(self):
+        self.requests = []
+        self.next = None
+
+    def request(self, method, uri, headers=None, bodyProducer=None):
+        self.requests.append((method, uri, headers, bodyProducer))
+
+    def setNextResponse(response):
+
+
+    # {'reactor': &lt;contrib.performance.loadtest.trafficlogger.(Logged Reactor) object at 0x10d1860d0&gt;, 'title': '10.11 Intern', 'self': &lt;contrib.performance.loadtest.requester.Requester object at 0x10d184a10&gt;, 'auth': {'digest': &lt;urllib2.HTTPDigestAuthHandler instance at 0x10d192128&gt;, 'basic': &lt;urllib2.HTTPBasicAuthHandler instance at 0x10d180fc8&gt;}, 'headers': {'Connection': ['keep-alive'], 'Accept-Language': ['en-us'], 'Accept-Encoding': ['gzip,deflate'], 'Accept': ['*/*'], 'User-Agent': ['Mac+OS+X/10.11 (15A216g) CalendarAgent/353']}, 'client_id': 'a11bce96-f787-4096-91a3-44f7dbf38a06', 'root': 'https://127.0.0.1:8443', 'uid': u'user01'}
+    
+
+class RequesterTests(TestCase):
+    def setUp(self):
+        self.root = '/foo/bar/'
+        self.headers = Headers({
+            'Connection': ['keep-alive'],
+            'Accept-Language': ['en-us'],
+            'Accept-Encoding': ['gzip,deflate'],
+            'Accept': ['*/*'],
+            'User-Agent': ['Mac+OS+X/10.11 (15A216g) CalendarAgent/353'
+        }
+        self.title = 'Requester '
+
+    self,
+        root,
+        headers,
+        title,
+        uid,
+        client_id,
+        auth,
+        reactor
+
+    
+
+class IncorrectResponseCodeTests(TestCase):
+    pass
+
+class WebClientContextFactoryTests(TestCase):
+    pass
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServerbranchesuserssredmondclientsimcontribperformanceloadtestteststest_resourcespy"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_resources.py ( => )</h4>
<pre class="diff"><span>
<span class="info">Added: CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_templates.py
===================================================================
</span><del>--- CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_templates.py                                (rev 0)
</del><ins>+++ CalendarServer/branches/users/sredmond/clientsim/contrib/performance/loadtest/tests/test_templates.py        2015-08-18 18:04:26 UTC (rev 15051)
</ins><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+# -*- test-case-name: contrib.performance.loadtest.test_templates -*-
+##
+# Copyright (c) 2010-2015 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# 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 &quot;AS IS&quot; 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.
+#
+##
+&quot;&quot;&quot;
+Tests for loadtest.templates
+&quot;&quot;&quot;
+
+from twisted.trial.unittest import TestCase
+
+from contrib.performance.loadtest.templates import eventTemplate, alarmTemplate, taskTemplate
+
+&quot;&quot;&quot;
+ensure they're all comps
+and that they are all vcalendars
+with the right prodid and calscale and version
+and that they have the corresponding component
+and that each comp has its required properties
+and that they are all v***
+
+&quot;&quot;&quot;
+
+class TemplateTests(TestCase):
+
+
+    def assertTemplateIs(self, component, ):
+        pass
+
+    def test_components(self):
+
+
+    def test_eventTemplate(self):
+        runTests(eventTemplate, component_name=&quot;VEVENT&quot;, required=&quot;&quot;)
</ins></span></pre>
</div>
</div>

</body>
</html>