~ahasenack/landscape-client/landscape-client-1.5.5-0ubuntu0.9.04.0

« back to all changes in this revision

Viewing changes to landscape/broker/tests/test_ping.py

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-09-08 16:35:57 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080908163557-l3ixzj5dxz37wnw2
Tags: 1.0.18-0ubuntu1
New upstream release 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from landscape.tests.helpers import LandscapeTest, FakeRemoteBrokerHelper
 
2
 
 
3
from twisted.internet.defer import succeed, fail
 
4
 
 
5
from landscape.lib.bpickle import dumps
 
6
from landscape.lib.fetch import fetch
 
7
from landscape.broker.ping import PingClient, Pinger
 
8
from landscape.broker.registration import Identity
 
9
 
 
10
 
 
11
class FakePageGetter(object):
 
12
    """An fake web client."""
 
13
 
 
14
    def __init__(self, response):
 
15
        self.response = response
 
16
        self.fetches = []
 
17
 
 
18
    def get_page(self, url, post, headers, data):
 
19
        """
 
20
        A method which is supposed to act like a limited version of
 
21
        L{landscape.lib.fetch.fetch}.
 
22
 
 
23
        Record attempts to get pages, and return a deferred with pre-cooked
 
24
        data.
 
25
        """
 
26
        self.fetches.append((url, post, headers, data))
 
27
        return dumps(self.response)
 
28
 
 
29
    def failing_get_page(self, url, post, headers, data):
 
30
        """
 
31
        A method which is supposed to act like a limited version of
 
32
        L{landscape.lib.fetch.fetch}.
 
33
 
 
34
        Record attempts to get pages, and return a deferred with pre-cooked
 
35
        data.
 
36
        """
 
37
        raise AssertionError("That's a failure!")
 
38
 
 
39
 
 
40
class PingClientTest(LandscapeTest):
 
41
 
 
42
    helpers = [FakeRemoteBrokerHelper]
 
43
 
 
44
    def test_default_get_page(self):
 
45
        """
 
46
        The C{get_page} argument to L{PingClient} should be optional, and
 
47
        default to L{twisted.web.client.getPage}.
 
48
        """
 
49
        client = PingClient(None, None, None)
 
50
        self.assertEqual(client.get_page, fetch)
 
51
 
 
52
    def test_ping(self):
 
53
        """
 
54
        L{PingClient} should be able to send a web request to a specified URL
 
55
        about a particular insecure ID.
 
56
        """
 
57
        client = FakePageGetter(None)
 
58
        self.broker_service.identity.insecure_id = 10
 
59
        url = "http://localhost/ping"
 
60
        pinger = PingClient(self.broker_service.reactor, url,
 
61
                            self.broker_service.identity,
 
62
                            get_page=client.get_page)
 
63
        pinger.ping()
 
64
        self.assertEquals(
 
65
            client.fetches,
 
66
            [(url, True, {"Content-Type": "application/x-www-form-urlencoded"},
 
67
              "insecure_id=10")])
 
68
 
 
69
    def test_ping_no_insecure_id(self):
 
70
        """
 
71
        If a L{PingClient} does not have an insecure-id yet, then the ping
 
72
        should not happen.
 
73
        """
 
74
        client = FakePageGetter(None)
 
75
        url = "http://localhost/ping"
 
76
        pinger = PingClient(self.broker_service.reactor,
 
77
                            url, self.broker_service.identity,
 
78
                            get_page=client.get_page)
 
79
        d = pinger.ping()
 
80
        d.addCallback(self.assertEqual, False)
 
81
        self.assertEquals(client.fetches, [])
 
82
 
 
83
    def test_respond(self):
 
84
        """
 
85
        The L{PingClient.ping} fire the Deferred it returns with True if the
 
86
        web request indicates that the computer has messages.
 
87
        """
 
88
        self.broker_service.identity.insecure_id = 23
 
89
        client = FakePageGetter({"messages": True})
 
90
        pinger = PingClient(self.broker_service.reactor,
 
91
                            None, self.broker_service.identity,
 
92
                            get_page=client.get_page)
 
93
        d = pinger.ping()
 
94
        d.addCallback(self.assertEqual, True)
 
95
 
 
96
    def test_errback(self):
 
97
        """
 
98
        If a L{PingClient} does not have an insecure-id yet, then the ping
 
99
        should not happen.
 
100
        """
 
101
        self.broker_service.identity.insecure_id = 23
 
102
        client = FakePageGetter(None)
 
103
        url = "http://localhost/ping"
 
104
        pinger = PingClient(self.broker_service.reactor,
 
105
                            url, self.broker_service.identity,
 
106
                            get_page=client.failing_get_page)
 
107
        d = pinger.ping()
 
108
        failures = []
 
109
        def errback(failure):
 
110
            failures.append(failure)
 
111
        d.addErrback(errback)
 
112
        self.assertEquals(len(failures), 1)
 
113
        self.assertEquals(failures[0].getErrorMessage(), "That's a failure!")
 
114
        self.assertEquals(failures[0].type, AssertionError)
 
115
 
 
116
 
 
117
class FakePingClient(object):
 
118
 
 
119
    def __init__(self):
 
120
        self.response = False
 
121
        self.pings = 0
 
122
 
 
123
    def ping(self):
 
124
        self.pings += 1
 
125
        return succeed(self.response)
 
126
 
 
127
 
 
128
class PingerTest(LandscapeTest):
 
129
 
 
130
    helpers = [FakeRemoteBrokerHelper]
 
131
 
 
132
    # Tell the Plugin helper to not add a MessageExchange plugin, to interfere
 
133
    # with our code which asserts stuff about when *our* plugin fires
 
134
    # exchanges.
 
135
    install_exchanger = False
 
136
 
 
137
    def setUp(self):
 
138
        super(PingerTest, self).setUp()
 
139
        self.url = "http://localhost:8081/whatever"
 
140
        self.ping_client = FakePingClient()
 
141
        def factory(reactor, url, insecure_id):
 
142
            self.ping_client.url = url
 
143
            self.ping_client.insecure_id = insecure_id
 
144
            return self.ping_client
 
145
        self.pinger = Pinger(self.broker_service.reactor,
 
146
                             self.url, self.broker_service.identity,
 
147
                             self.broker_service.exchanger,
 
148
                             interval=10, ping_client_factory=factory)
 
149
 
 
150
    def test_default_ping_client(self):
 
151
        """
 
152
        The C{ping_client_factory} argument to L{Pinger} should be optional,
 
153
        and default to L{PingClient}.
 
154
        """
 
155
        pinger = Pinger(self.broker_service.reactor, "http://foo.com/",
 
156
                        self.broker_service.identity,
 
157
                        self.broker_service.exchanger)
 
158
        self.assertEqual(pinger.ping_client_factory, PingClient)
 
159
 
 
160
    def test_occasional_ping(self):
 
161
        """
 
162
        The L{Pinger} should be able to occasionally ask if there are
 
163
        messages.
 
164
        """
 
165
        self.pinger.start()
 
166
        self.broker_service.identity.insecure_id = 23
 
167
        self.broker_service.reactor.advance(9)
 
168
        self.assertEquals(self.ping_client.pings, 0)
 
169
        self.broker_service.reactor.advance(1)
 
170
        self.assertEquals(self.ping_client.pings, 1)
 
171
 
 
172
    def test_set_insecure_id_message(self):
 
173
        """
 
174
        L{Pinger} should register a handler for the 'set-id' message
 
175
        so that it can start pinging when an insecure-id has been
 
176
        received.
 
177
        """
 
178
        self.pinger.start()
 
179
        self.broker_service.identity.insecure_id = 42
 
180
        self.broker_service.reactor.advance(10)
 
181
        self.assertEquals(self.ping_client.pings, 1)
 
182
 
 
183
    def test_load_insecure_id(self):
 
184
        """
 
185
        If the insecure-id has already been saved when the plugin is
 
186
        registered, it should immediately start pinging.
 
187
        """
 
188
        self.broker_service.identity.insecure_id = 42
 
189
        self.pinger.start()
 
190
        self.broker_service.reactor.advance(10)
 
191
        self.assertEqual(self.ping_client.pings, 1)
 
192
 
 
193
    def test_response(self):
 
194
        """
 
195
        When a ping indicates there are messages, an exchange should occur.
 
196
        """
 
197
        self.pinger.start()
 
198
        self.broker_service.identity.insecure_id = 42
 
199
        exchanged = []
 
200
        self.ping_client.response = True
 
201
 
 
202
        # 70 = ping delay + urgent exchange delay
 
203
        self.broker_service.reactor.advance(70)
 
204
 
 
205
        self.assertEquals(len(self.broker_service.transport.payloads), 1)
 
206
 
 
207
    def test_negative_response(self):
 
208
        """
 
209
        When a ping indicates there are no messages, no exchange should occur.
 
210
        """
 
211
        self.pinger.start()
 
212
        self.broker_service.identity.insecure_id = 42
 
213
        exchanged = []
 
214
        self.ping_client.response = False
 
215
        self.broker_service.reactor.advance(10)
 
216
        self.assertEquals(len(self.broker_service.transport.payloads), 0)
 
217
 
 
218
    def test_ping_error(self):
 
219
        """
 
220
        When the web interaction fails for some reason, a message
 
221
        should be logged.
 
222
        """
 
223
        self.log_helper.ignore_errors(ZeroDivisionError)
 
224
        self.pinger.start()
 
225
        self.broker_service.identity.insecure_id = 42
 
226
 
 
227
        def bad_ping():
 
228
            return fail(ZeroDivisionError("Couldn't fetch page"))
 
229
        self.ping_client.ping = bad_ping
 
230
 
 
231
        self.broker_service.reactor.advance(10)
 
232
 
 
233
        log = self.logfile.getvalue()
 
234
        self.assertTrue("Error contacting ping server at "
 
235
                        "http://localhost:8081/whatever" in log)
 
236
        self.assertTrue("ZeroDivisionError" in log)
 
237
        self.assertTrue("Couldn't fetch page" in log)
 
238
 
 
239
    def test_get_interval(self):
 
240
        self.assertEquals(self.pinger.get_interval(), 10)
 
241
 
 
242
    def test_set_intervals_handling(self):
 
243
        self.pinger.start()
 
244
 
 
245
        self.broker_service.reactor.fire("message",
 
246
                                         {"type": "set-intervals", "ping": 73})
 
247
        self.assertEquals(self.pinger.get_interval(), 73)
 
248
 
 
249
        # The server may set specific intervals only, not including the ping.
 
250
        self.broker_service.reactor.fire("message", {"type": "set-intervals"})
 
251
        self.assertEquals(self.pinger.get_interval(), 73)
 
252
 
 
253
        self.broker_service.identity.insecure_id = 23
 
254
        self.broker_service.reactor.advance(72)
 
255
        self.assertEquals(self.ping_client.pings, 0)
 
256
        self.broker_service.reactor.advance(1)
 
257
        self.assertEquals(self.ping_client.pings, 1)