3
from landscape.broker.registration import (
4
RegistrationHandler, Identity, InvalidCredentialsError)
6
from landscape.tests.helpers import LandscapeTest, ExchangeHelper
9
class RegistrationTest(LandscapeTest):
11
helpers = [ExchangeHelper]
14
super(RegistrationTest, self).setUp()
15
self.config = self.broker_service.config
16
self.identity = self.broker_service.identity
17
self.handler = self.broker_service.registration
18
logging.getLogger().setLevel(logging.INFO)
20
def mock_gethostname(self, replay=True):
21
gethostname_mock = self.mocker.replace("socket.gethostname")
23
self.mocker.result("ooga")
27
def check_persist_property(self, attr, persist_name):
29
self.assertEquals(getattr(self.identity, attr), None,
30
"%r attribute should default to None, not %r" %
31
(attr, getattr(self.identity, attr)))
32
setattr(self.identity, attr, value)
33
self.assertEquals(getattr(self.identity, attr), value,
34
"%r attribute should be %r, not %r" %
35
(attr, value, getattr(self.identity, attr)))
36
self.assertEquals(self.persist.get(persist_name), value,
37
"%r not set to %r in persist" % (persist_name, value))
39
def check_config_property(self, attr):
41
setattr(self.config, attr, value)
42
self.assertEquals(getattr(self.identity, attr), value,
43
"%r attribute should be %r, not %r" %
44
(attr, value, getattr(self.identity, attr)))
46
def test_secure_id(self):
47
self.check_persist_property("secure_id",
48
"registration.secure-id")
50
def test_insecure_id(self):
51
self.check_persist_property("insecure_id",
52
"registration.insecure-id")
54
def test_computer_title(self):
55
self.check_config_property("computer_title")
57
def test_account_name(self):
58
self.check_config_property("account_name")
60
def test_registration_password(self):
61
self.check_config_property("registration_password")
63
def test_server_initiated_id_changing(self):
65
The server must be able to ask a client to change its secure
66
and insecure ids even if no requests were sent.
68
self.reactor.fire("message",
69
{"type": "set-id", "id": "abc", "insecure-id": "def"})
70
self.assertEquals(self.identity.secure_id, "abc")
71
self.assertEquals(self.identity.insecure_id, "def")
73
def test_registration_done_event(self):
75
When new ids are received from the server, a "registration-done"
78
reactor_mock = self.mocker.patch(self.reactor)
79
reactor_mock.fire("registration-done")
81
self.reactor.fire("message",
82
{"type": "set-id", "id": "abc", "insecure-id": "def"})
84
def test_unknown_id(self):
85
self.identity.secure_id = "old_id"
86
self.identity.insecure_id = "old_id"
87
self.mstore.set_accepted_types(["register"])
88
self.reactor.fire("message", {"type": "unknown-id"})
89
self.assertEquals(self.identity.secure_id, None)
90
self.assertEquals(self.identity.insecure_id, None)
92
def test_should_register(self):
93
self.mstore.set_accepted_types(["register"])
94
self.config.computer_title = "Computer Title"
95
self.config.account_name = "account_name"
96
self.assertTrue(self.handler.should_register())
98
def test_should_register_with_existing_id(self):
99
self.mstore.set_accepted_types(["register"])
100
self.identity.secure_id = "secure"
101
self.config.computer_title = "Computer Title"
102
self.config.account_name = "account_name"
103
self.assertFalse(self.handler.should_register())
105
def test_should_register_without_computer_title(self):
106
self.mstore.set_accepted_types(["register"])
107
self.config.computer_title = None
108
self.assertFalse(self.handler.should_register())
110
def test_should_register_without_account_name(self):
111
self.mstore.set_accepted_types(["register"])
112
self.config.account_name = None
113
self.assertFalse(self.handler.should_register())
115
def test_should_register_with_unaccepted_message(self):
116
self.assertFalse(self.handler.should_register())
118
def test_queue_message_on_exchange(self):
120
When a computer_title and account_name are available, no
121
secure_id is set, and an exchange is about to happen,
122
queue a registration message.
124
self.mock_gethostname()
125
self.mstore.set_accepted_types(["register"])
126
self.config.computer_title = "Computer Title"
127
self.config.account_name = "account_name"
128
self.reactor.fire("pre-exchange")
129
self.assertMessages(self.mstore.get_pending_messages(),
130
[{"type": "register",
131
"computer_title": "Computer Title",
132
"account_name": "account_name",
133
"registration_password": None,
136
self.assertEquals(self.logfile.getvalue().strip(),
137
"INFO: Queueing message to register with account "
138
"'account_name' without a password.")
140
def test_queue_message_on_exchange_with_password(self):
141
"""If a registration password is available, we pass it on!"""
142
self.mock_gethostname()
143
self.mstore.set_accepted_types(["register"])
144
self.config.computer_title = "Computer Title"
145
self.config.account_name = "account_name"
146
self.config.registration_password = "SEKRET"
147
self.reactor.fire("pre-exchange")
148
self.assertMessages(self.mstore.get_pending_messages(),
149
[{"type": "register",
150
"computer_title": "Computer Title",
151
"account_name": "account_name",
152
"registration_password": "SEKRET",
155
self.assertEquals(self.logfile.getvalue().strip(),
156
"INFO: Queueing message to register with account "
157
"'account_name' with a password.")
159
def test_queueing_registration_message_resets_message_store(self):
161
When a registration message is queued, the store is reset
162
entirely, since everything else that was queued is meaningless
163
now that we're trying to register again.
165
self.mstore.set_accepted_types(["register", "test"])
166
self.mstore.add({"type": "test"})
167
self.config.computer_title = "Computer Title"
168
self.config.account_name = "account_name"
169
self.reactor.fire("pre-exchange")
170
messages = self.mstore.get_pending_messages()
171
self.assertEquals(len(messages), 1)
172
self.assertEquals(messages[0]["type"], "register")
174
def test_no_message_when_should_register_is_false(self):
175
"""If we already have a secure id, do not queue a register message.
177
handler_mock = self.mocker.patch(self.handler)
178
handler_mock.should_register()
179
self.mocker.result(False)
181
self.mstore.set_accepted_types(["register"])
182
self.config.computer_title = "Computer Title"
183
self.config.account_name = "account_name"
185
# If we didn't fake it, it'd work. We do that to ensure that
186
# all the needed data is in place, and that this method is
187
# really what decides if a message is sent or not. This way
188
# we can test it individually.
189
self.assertTrue(self.handler.should_register())
194
self.reactor.fire("pre-exchange")
195
self.assertMessages(self.mstore.get_pending_messages(), [])
197
def test_registration_failed_event(self):
199
The deferred returned by a registration request should fail
200
with L{InvalidCredentialsError} if the server responds with a
203
reactor_mock = self.mocker.patch(self.reactor)
204
reactor_mock.fire("registration-failed")
206
self.reactor.fire("message",
207
{"type": "registration", "info": "unknown-account"})
209
def test_registration_failed_event_not_fired_when_uncertain(self):
211
If the data in the registration message isn't what we expect,
212
the event isn't fired.
214
reactor_mock = self.mocker.patch(self.reactor)
215
reactor_mock.fire("registration-failed")
218
self.reactor.fire("message",
219
{"type": "registration", "info": "blah-blah"})
221
def test_register_resets_ids(self):
222
self.identity.secure_id = "foo"
223
self.identity.insecure_id = "bar"
224
self.handler.register()
225
self.assertEquals(self.identity.secure_id, None)
226
self.assertEquals(self.identity.insecure_id, None)
228
def test_register_calls_urgent_exchange(self):
229
exchanger_mock = self.mocker.patch(self.exchanger)
230
exchanger_mock.exchange()
231
self.mocker.passthrough()
233
self.handler.register()
235
def test_register_deferred_called_on_done(self):
236
# We don't want informational messages.
237
self.logger.setLevel(logging.WARNING)
240
d = self.handler.register()
241
def add_call(result):
242
self.assertEquals(result, None)
244
d.addCallback(add_call)
246
# This should somehow callback the deferred.
247
self.reactor.fire("message",
248
{"type": "set-id", "id": "abc", "insecure-id": "def"})
250
self.assertEquals(calls, [1])
252
# Doing it again to ensure that the deferred isn't called twice.
253
self.reactor.fire("message",
254
{"type": "set-id", "id": "abc", "insecure-id": "def"})
256
self.assertEquals(calls, [1])
258
self.assertEquals(self.logfile.getvalue(), "")
260
def test_resynchronize_fired_when_registration_done(self):
265
self.reactor.call_on("resynchronize-clients", append)
267
self.handler.register()
269
# This should somehow callback the deferred.
270
self.reactor.fire("message",
271
{"type": "set-id", "id": "abc", "insecure-id": "def"})
273
self.assertEquals(results, [True])
275
def test_register_deferred_called_on_failed(self):
276
# We don't want informational messages.
277
self.logger.setLevel(logging.WARNING)
280
d = self.handler.register()
281
def add_call(failure):
282
exception = failure.value
283
self.assertTrue(isinstance(exception, InvalidCredentialsError))
285
d.addErrback(add_call)
287
# This should somehow callback the deferred.
288
self.reactor.fire("message",
289
{"type": "registration", "info": "unknown-account"})
291
self.assertEquals(calls, [1])
293
# Doing it again to ensure that the deferred isn't called twice.
294
self.reactor.fire("message",
295
{"type": "registration", "info": "unknown-account"})
297
self.assertEquals(calls, [1])
299
self.assertEquals(self.logfile.getvalue(), "")
301
def test_exchange_done_calls_exchange(self):
302
exchanger_mock = self.mocker.patch(self.exchanger)
303
exchanger_mock.exchange()
304
self.mocker.passthrough()
307
self.mstore.set_accepted_types(["register"])
308
self.config.computer_title = "Computer Title"
309
self.config.account_name = "account_name"
310
self.reactor.fire("exchange-done")
312
def test_exchange_done_wont_call_exchange_when_just_tried(self):
313
exchanger_mock = self.mocker.patch(self.exchanger)
314
exchanger_mock.exchange()
318
self.mstore.set_accepted_types(["register"])
319
self.config.computer_title = "Computer Title"
320
self.config.account_name = "account_name"
321
self.reactor.fire("pre-exchange")
322
self.reactor.fire("exchange-done")