4
4
from twisted.internet.defer import Deferred, fail
6
6
from landscape.lib.lock import lock_path
7
from landscape.lib.command import CommandError
9
from landscape.deployment import Configuration
10
from landscape.broker.remote import RemoteBroker
12
from landscape.package.taskhandler import PackageTaskHandler, run_task_handler
8
from landscape.package.taskhandler import (
9
PackageTaskHandlerConfiguration, PackageTaskHandler, run_task_handler,
13
11
from landscape.package.facade import SmartFacade
14
12
from landscape.package.store import HashIdStore, PackageStore
15
13
from landscape.package.tests.helpers import SmartFacadeHelper
17
15
from landscape.tests.helpers import (
18
LandscapeIsolatedTest, RemoteBrokerHelper)
16
LandscapeTest, LandscapeIsolatedTest, RemoteBrokerHelper)
19
17
from landscape.tests.mocker import ANY, ARGS, MATCH
23
21
return MATCH(lambda arg: type(arg) is match_type)
24
SAMPLE_LSB_RELEASE = "DISTRIB_CODENAME=codename\n"
26
27
class PackageTaskHandlerTest(LandscapeIsolatedTest):
28
29
helpers = [SmartFacadeHelper, RemoteBrokerHelper]
31
32
super(PackageTaskHandlerTest, self).setUp()
33
self.config = Configuration()
34
self.config = PackageTaskHandlerConfiguration()
34
35
self.store = PackageStore(self.makeFile())
36
self.handler = PackageTaskHandler(self.store, self.facade, self.remote, self.config)
36
self.handler = PackageTaskHandler(self.store, self.facade, self.remote,
38
39
def test_ensure_channels_reloaded(self):
39
40
self.assertEquals(len(self.facade.get_packages()), 0)
60
61
# Fake uuid, codename and arch
61
62
message_store = self.broker_service.message_store
62
63
message_store.set_server_uuid("uuid")
63
command_mock = self.mocker.replace("landscape.lib.command.run_command")
64
command_mock("lsb_release -cs")
65
self.mocker.result("codename")
64
self.handler.lsb_release_filename = self.makeFile(SAMPLE_LSB_RELEASE)
66
65
self.facade.set_arch("arch")
68
67
# Attach the hash=>id database to our store
83
82
message_store.set_server_uuid("uuid")
85
84
# Undetermined codename
86
command_mock = self.mocker.replace("landscape.lib.command.run_command")
87
command_mock("lsb_release -cs")
88
command_error = CommandError("lsb_release -cs", 1, "error")
89
self.mocker.throw(command_error)
91
# The failure should be properly logged
92
logging_mock = self.mocker.replace("logging.warning")
93
logging_mock("Couldn't determine which hash=>id database to use: %s" %
95
self.mocker.result(None)
99
result = self.handler.use_hash_id_db()
85
self.handler.lsb_release_filename = self.makeFile("Foo=bar")
87
# The failure should be properly logged
88
logging_mock = self.mocker.replace("logging.warning")
89
logging_mock("Couldn't determine which hash=>id database to use: "
90
"missing code-name key in %s" %
91
self.handler.lsb_release_filename)
92
self.mocker.result(None)
96
result = self.handler.use_hash_id_db()
99
def test_use_hash_id_db_wit_non_existing_lsb_release(self):
102
message_store = self.broker_service.message_store
103
message_store.set_server_uuid("uuid")
105
# Undetermined codename
106
self.handler.lsb_release_filename = self.makeFile()
108
# The failure should be properly logged
109
logging_mock = self.mocker.replace("logging.warning")
110
logging_mock("Couldn't determine which hash=>id database to use: "
111
"[Errno 2] No such file or directory: '%s'" %
112
self.handler.lsb_release_filename)
113
self.mocker.result(None)
117
result = self.handler.use_hash_id_db()
103
120
def test_wb_determine_hash_id_db_filename_server_uuid_is_none(self):
109
126
message_store.set_server_uuid(None)
111
128
result = self.handler._determine_hash_id_db_filename()
112
130
def callback(hash_id_db_filename):
113
131
self.assertIs(hash_id_db_filename, None)
114
132
result.addCallback(callback)
117
135
def test_use_hash_id_db_undetermined_server_uuid(self):
119
137
If the server-uuid can't be determined for some reason, no hash-id db
139
158
# Fake uuid and codename
140
159
message_store = self.broker_service.message_store
141
160
message_store.set_server_uuid("uuid")
142
command_mock = self.mocker.replace("landscape.lib.command.run_command")
143
command_mock("lsb_release -cs")
144
self.mocker.result("codename")
161
self.handler.lsb_release_filename = self.makeFile(SAMPLE_LSB_RELEASE)
146
163
# Undetermined arch
147
164
self.facade.set_arch(None)
166
183
# Fake uuid, codename and arch
167
184
message_store = self.broker_service.message_store
168
185
message_store.set_server_uuid("uuid")
169
command_mock = self.mocker.replace("landscape.lib.command.run_command")
170
command_mock("lsb_release -cs")
171
self.mocker.result("codename")
186
self.handler.lsb_release_filename = self.makeFile(SAMPLE_LSB_RELEASE)
172
187
self.facade.set_arch("arch")
194
209
# Fake uuid, codename and arch
195
210
message_store = self.broker_service.message_store
196
211
message_store.set_server_uuid("uuid")
197
command_mock = self.mocker.replace("landscape.lib.command.run_command")
198
command_mock("lsb_release -cs")
199
self.mocker.result("codename")
212
self.handler.lsb_release_filename = self.makeFile(SAMPLE_LSB_RELEASE)
200
213
self.facade.set_arch("arch")
202
215
# The failure should be properly logged
257
271
results[0].callback(None)
258
272
self.assertEquals(stash, [0, 1])
259
self.assertFalse(handle_tasks_result.called)
273
self.assertTrue(handle_tasks_result.called)
260
274
self.assertEquals(self.store.get_next_task(queue_name).data, 2)
262
276
results[2].callback(None)
305
320
# Prepare the mock objects.
306
321
lock_path_mock = self.mocker.replace("landscape.lib.lock.lock_path",
307
322
passthrough=False)
308
install_mock = self.mocker.replace("twisted.internet."
309
"glib2reactor.install")
323
install_mock = self.mocker.replace("landscape.reactor.install")
310
324
reactor_mock = self.mocker.replace("twisted.internet.reactor",
311
325
passthrough=False)
312
326
init_logging_mock = self.mocker.replace("landscape.deployment"
330
344
# Once locking is done, it's safe to start logging without
331
345
# corrupting the file. We don't want any output unless it's
332
346
# breaking badly, so the quiet option should be set.
333
init_logging_mock(ISTYPE(Configuration), "package-default")
347
init_logging_mock(ISTYPE(PackageTaskHandlerConfiguration),
348
"package-task-handler")
335
350
# Then, it must create an instance of the TaskHandler subclass
336
351
# passed in as a parameter. We'll keep track of the arguments
337
352
# given and verify them later.
338
353
handler_args = []
339
handler_mock = HandlerMock(ANY, ANY, ANY, ANY)
354
HandlerMock(ANY, ANY, ANY, ANY)
340
355
self.mocker.passthrough() # Let the real constructor run for testing.
341
356
self.mocker.call(lambda *args: handler_args.extend(args))
343
# Finally, the task handler must be run, and will return a deferred.
344
# We'll return a real deferred so that we can call it back and test
345
# whatever was hooked in as well.
346
deferred = Deferred()
348
self.mocker.result(deferred)
359
reactor_mock.callWhenRunning(ANY)
360
self.mocker.call(lambda callback: to_call.append(callback))
350
362
# With all of that done, the Twisted reactor must be run, so that
351
363
# deferred tasks are correctly performed.
372
result = run_task_handler(HandlerMock,
373
["--data-path", data_path,
384
run_task_handler(HandlerMock, ["--data-path", data_path,
376
387
# reactor.stop() wasn't run yet, so it must fail right now.
377
388
self.assertRaises(AssertionError, self.mocker.verify)
379
390
# DO THE REST OF IT! :-)
380
result.callback(None)
382
393
# Are we there yet!?
383
394
self.mocker.verify()
390
401
# Verify if the arguments to the reporter constructor were correct.
391
402
self.assertEquals(type(store), PackageStore)
392
403
self.assertEquals(type(facade), SmartFacade)
393
self.assertEquals(type(broker), RemoteBroker)
394
self.assertEquals(type(config), Configuration)
404
self.assertEquals(type(broker), LazyRemoteBroker)
405
self.assertEquals(type(config), PackageTaskHandlerConfiguration)
396
407
# Let's see if the store path is where it should be.
397
408
filename = os.path.join(data_path, "package", "database")
425
435
def test_run_task_handler_when_already_locked_and_quiet_option(self):
426
436
data_path = self.makeDir()
428
install_mock = self.mocker.replace("twisted.internet."
429
"glib2reactor.install")
438
install_mock = self.mocker.replace("landscape.reactor.install")
432
441
self.mocker.replay()
445
454
def test_errors_in_tasks_are_printed_and_exit_program(self):
446
455
# Ignore a bunch of crap that we don't care about
447
install_mock = self.mocker.replace("twisted.internet."
448
"glib2reactor.install")
456
install_mock = self.mocker.replace("landscape.reactor.install")
450
458
reactor_mock = self.mocker.proxy(reactor)
451
459
init_logging_mock = self.mocker.replace("landscape.deployment"
481
489
self.assertIn("MyException", self.logfile.getvalue())
483
491
return done.addCallback(everything_stopped)
494
class LazyRemoteBrokerTest(LandscapeTest):
497
def test_wb_is_lazy(self):
499
The L{LazyRemoteBroker} class doesn't initialize the actual remote
500
broker until one of its attributes gets actually accessed.
502
self.broker = LazyRemoteBroker("bus")
503
self.assertIdentical(self.broker._remote, None)
504
get_bus_mock = self.mocker.replace("landscape.lib.dbus_util.get_bus")
506
self.mocker.result("bus_object")
508
self.assertEquals(self.broker.bus, "bus_object")