~ubuntu-branches/ubuntu/utopic/calendarserver/utopic

« back to all changes in this revision

Viewing changes to calendarserver/push/test/test_applepush.py

  • Committer: Package Import Robot
  • Author(s): Rahul Amaram
  • Date: 2012-05-29 18:12:12 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20120529181212-mxjdfncopy6vou0f
Tags: 3.2+dfsg-1
* New upstream release
* Moved from using cdbs to dh sequencer
* Modified calenderserver init.d script based on /etc/init.d/skeleton script
* Removed ldapdirectory.patch as the OpenLDAP directory service has been 
  merged upstream
* Moved package to section "net" as calendarserver is more service than 
  library (Closes: #665859)
* Changed Architecture of calendarserver package to any as the package
  now includes compiled architecture dependent Python extensions
* Unowned files are no longer left on the system upon purging
  (Closes: #668731)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##
 
2
# Copyright (c) 2011 Apple Inc. All rights reserved.
 
3
#
 
4
# Licensed under the Apache License, Version 2.0 (the "License");
 
5
# you may not use this file except in compliance with the License.
 
6
# You may obtain a copy of the License at
 
7
#
 
8
# http://www.apache.org/licenses/LICENSE-2.0
 
9
#
 
10
# Unless required by applicable law or agreed to in writing, software
 
11
# distributed under the License is distributed on an "AS IS" BASIS,
 
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
# See the License for the specific language governing permissions and
 
14
# limitations under the License.
 
15
##
 
16
 
 
17
from calendarserver.push.applepush import (
 
18
    ApplePushNotifierService, APNProviderProtocol
 
19
)
 
20
from twistedcaldav.test.util import TestCase
 
21
from twisted.internet.defer import inlineCallbacks
 
22
from twisted.internet.task import Clock
 
23
import struct
 
24
from txdav.common.datastore.test.util import buildStore, CommonCommonTests
 
25
 
 
26
class ApplePushNotifierServiceTests(CommonCommonTests, TestCase):
 
27
 
 
28
    @inlineCallbacks
 
29
    def setUp(self):
 
30
        yield super(ApplePushNotifierServiceTests, self).setUp()
 
31
        self.store = yield buildStore(self, None)
 
32
 
 
33
    @inlineCallbacks
 
34
    def test_ApplePushNotifierService(self):
 
35
 
 
36
        settings = {
 
37
            "Service" : "calendarserver.push.applepush.ApplePushNotifierService",
 
38
            "Enabled" : True,
 
39
            "SubscriptionURL" : "apn",
 
40
            "DataHost" : "calendars.example.com",
 
41
            "ProviderHost" : "gateway.push.apple.com",
 
42
            "ProviderPort" : 2195,
 
43
            "FeedbackHost" : "feedback.push.apple.com",
 
44
            "FeedbackPort" : 2196,
 
45
            "FeedbackUpdateSeconds" : 300,
 
46
            "CalDAV" : {
 
47
                "CertificatePath" : "caldav.cer",
 
48
                "PrivateKeyPath" : "caldav.pem",
 
49
                "Topic" : "caldav_topic",
 
50
            },
 
51
            "CardDAV" : {
 
52
                "CertificatePath" : "carddav.cer",
 
53
                "PrivateKeyPath" : "carddav.pem",
 
54
                "Topic" : "carddav_topic",
 
55
            },
 
56
        }
 
57
 
 
58
 
 
59
        # Add subscriptions
 
60
        txn = self.store.newTransaction()
 
61
        token = "2d0d55cd7f98bcb81c6e24abcdc35168254c7846a43e2828b1ba5a8f82e219df"
 
62
        key1 = "/CalDAV/calendars.example.com/user01/calendar/"
 
63
        timestamp1 = 1000
 
64
        guid = "D2256BCC-48E2-42D1-BD89-CBA1E4CCDFFB"
 
65
        yield txn.addAPNSubscription(token, key1, timestamp1, guid)
 
66
 
 
67
        key2 = "/CalDAV/calendars.example.com/user02/calendar/"
 
68
        timestamp2 = 3000
 
69
        yield txn.addAPNSubscription(token, key2, timestamp2, guid)
 
70
        yield txn.commit()
 
71
 
 
72
        # Set up the service
 
73
        clock = Clock()
 
74
        service = (yield ApplePushNotifierService.makeService(settings,
 
75
            self.store, testConnectorClass=TestConnector, reactor=clock))
 
76
        self.assertEquals(set(service.providers.keys()), set(["CalDAV","CardDAV"]))
 
77
        self.assertEquals(set(service.feedbacks.keys()), set(["CalDAV","CardDAV"]))
 
78
 
 
79
        # First, enqueue a notification while we have no connection, in this
 
80
        # case by doing it prior to startService()
 
81
 
 
82
        # Notification arrives from calendar server
 
83
        yield service.enqueue("update", "CalDAV|user01/calendar")
 
84
 
 
85
        # The notification should be in the queue
 
86
        self.assertEquals(service.providers["CalDAV"].queue, [(token, key1)])
 
87
 
 
88
        # Start the service, making the connection which should service the
 
89
        # queue
 
90
        service.startService()
 
91
 
 
92
        # The queue should be empty
 
93
        self.assertEquals(service.providers["CalDAV"].queue, [])
 
94
 
 
95
        # Verify data sent to APN
 
96
        connector = service.providers["CalDAV"].testConnector
 
97
        rawData = connector.transport.data
 
98
        self.assertEquals(len(rawData), 103)
 
99
        data = struct.unpack("!BIIH32sH", rawData[:45])
 
100
        self.assertEquals(data[0], 1) # command
 
101
        self.assertEquals(data[4].encode("hex"), token.replace(" ", "")) # token
 
102
        payloadLength = data[5]
 
103
        payload = struct.unpack("%ds" % (payloadLength,),
 
104
            rawData[45:])
 
105
        self.assertEquals(payload[0], '{"key" : "%s"}' % (key1,))
 
106
 
 
107
        # Simulate an error
 
108
        errorData = struct.pack("!BBI", APNProviderProtocol.COMMAND_ERROR, 1, 1)
 
109
        yield connector.receiveData(errorData)
 
110
        clock.advance(301)
 
111
 
 
112
        # Prior to feedback, there are 2 subscriptions
 
113
        txn = self.store.newTransaction()
 
114
        subscriptions = (yield txn.apnSubscriptionsByToken(token))
 
115
        yield txn.commit()
 
116
        self.assertEquals(len(subscriptions), 2)
 
117
 
 
118
        # Simulate feedback
 
119
        timestamp = 2000
 
120
        connector = service.feedbacks["CalDAV"].testConnector
 
121
        binaryToken = token.decode("hex")
 
122
        feedbackData = struct.pack("!IH32s", timestamp, len(binaryToken),
 
123
            binaryToken)
 
124
        yield connector.receiveData(feedbackData)
 
125
 
 
126
        # The second subscription should now be gone
 
127
        # Prior to feedback, there are 2 subscriptions
 
128
        txn = self.store.newTransaction()
 
129
        subscriptions = (yield txn.apnSubscriptionsByToken(token))
 
130
        yield txn.commit()
 
131
        self.assertEquals(len(subscriptions), 1)
 
132
 
 
133
 
 
134
class TestConnector(object):
 
135
 
 
136
    def connect(self, service, factory):
 
137
        self.service = service
 
138
        service.protocol = factory.buildProtocol(None)
 
139
        service.connected = 1
 
140
        self.transport = StubTransport()
 
141
        service.protocol.makeConnection(self.transport)
 
142
 
 
143
    def receiveData(self, data):
 
144
        return self.service.protocol.dataReceived(data)
 
145
 
 
146
 
 
147
class StubTransport(object):
 
148
 
 
149
    def __init__(self):
 
150
        self.data = None
 
151
 
 
152
    def write(self, data):
 
153
        self.data = data