Merge lp:~adam-collard/landscape-client/mocker-replace-configuration-part-deux into lp:~landscape/landscape-client/trunk
- mocker-replace-configuration-part-deux
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Adam Collard | ||||
Approved revision: | 852 | ||||
Merged at revision: | 889 | ||||
Proposed branch: | lp:~adam-collard/landscape-client/mocker-replace-configuration-part-deux | ||||
Merge into: | lp:~landscape/landscape-client/trunk | ||||
Diff against target: |
1387 lines (+397/-489) 1 file modified
landscape/tests/test_configuration.py (+397/-489) |
||||
To merge this branch: | bzr merge lp:~adam-collard/landscape-client/mocker-replace-configuration-part-deux | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Данило Шеган (community) | Approve | ||
🤖 Landscape Builder | test results | Approve | |
Chris Glass (community) | Approve | ||
Review via email:
|
Commit message
Convert ConfigurationFu
Follow on branches will cover the remaining use of mocker in the tests.
Description of the change
Convert ConfigurationFu
Follow on branches will cover the remaining use of mocker in the tests.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Данило Шеган (danilo) wrote : | # |
For the lint I mentioned, I am still seeing the following:
=== pyflakes ===
landscape/
landscape/
landscape/
landscape/
(on xenial)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 851
Branch: lp:~adam-collard/landscape-client/mocker-replace-configuration-part-deux
Jenkins: https:/
- 852. By Adam Collard
-
Fix typo (thanks danilo!)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 852
Branch: lp:~adam-collard/landscape-client/mocker-replace-configuration-part-deux
Jenkins: https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Данило Шеган (danilo) wrote : | # |
Here's a reluctant +1 for you, Adam.
Preview Diff
1 | === modified file 'landscape/tests/test_configuration.py' |
2 | --- landscape/tests/test_configuration.py 2016-06-15 22:56:46 +0000 |
3 | +++ landscape/tests/test_configuration.py 2016-06-16 16:07:42 +0000 |
4 | @@ -14,17 +14,16 @@ |
5 | from landscape.configuration import ( |
6 | print_text, LandscapeSetupScript, LandscapeSetupConfiguration, |
7 | register, setup, main, setup_init_script_and_start_client, |
8 | - stop_client_and_disable_init_script, ConfigurationError, |
9 | + ConfigurationError, |
10 | ImportOptionError, store_public_key_data, |
11 | bootstrap_tree, got_connection, success, failure, exchange_failure, |
12 | handle_registration_errors, done, got_error, report_registration_outcome, |
13 | determine_exit_code) |
14 | from landscape.lib.amp import MethodCallError |
15 | from landscape.lib.fetch import HTTPCodeError, PyCurlError |
16 | -from landscape.sysvconfig import SysVConfig, ProcessError |
17 | +from landscape.sysvconfig import ProcessError |
18 | from landscape.tests.helpers import FakeBrokerServiceHelper |
19 | from landscape.tests.helpers import LandscapeTest, EnvironSaverHelper |
20 | -from landscape.tests.mocker import ANY, CONTAINS, expect |
21 | |
22 | |
23 | class LandscapeConfigurationTest(LandscapeTest): |
24 | @@ -730,7 +729,8 @@ |
25 | |
26 | class BootstrapTreeTest(LandscapeConfigurationTest): |
27 | |
28 | - def test_bootstrap_tree(self): |
29 | + @mock.patch("os.chmod") |
30 | + def test_bootstrap_tree(self, mock_chmod): |
31 | """ |
32 | The L{bootstrap_tree} function creates the client dir and |
33 | /annotations.d under it with the correct permissions. |
34 | @@ -738,13 +738,10 @@ |
35 | client_path = self.makeDir() |
36 | annotations_path = os.path.join(client_path, "annotations.d") |
37 | |
38 | - mock_chmod = self.mocker.replace("os.chmod") |
39 | - mock_chmod(client_path, 0755) |
40 | - mock_chmod(annotations_path, 0755) |
41 | - self.mocker.replay() |
42 | - |
43 | config = self.get_config([], data_path=client_path) |
44 | bootstrap_tree(config) |
45 | + mock_chmod.assert_any_call(client_path, 0755) |
46 | + mock_chmod.assert_called_with(annotations_path, 0755) |
47 | self.assertTrue(os.path.isdir(client_path)) |
48 | self.assertTrue(os.path.isdir(annotations_path)) |
49 | |
50 | @@ -754,21 +751,12 @@ |
51 | pass |
52 | |
53 | |
54 | +@mock.patch("landscape.configuration.bootstrap_tree") |
55 | +@mock.patch("os.getuid", return_value=0) |
56 | class ConfigurationFunctionsTest(LandscapeConfigurationTest): |
57 | |
58 | helpers = [EnvironSaverHelper] |
59 | |
60 | - def setUp(self): |
61 | - super(ConfigurationFunctionsTest, self).setUp() |
62 | - self.mocker.replace("os.getuid")() |
63 | - self.mocker.count(0, None) |
64 | - self.mocker.result(0) |
65 | - |
66 | - # Make bootstrap_tree a no-op as a a non-root user can't change |
67 | - # ownership. |
68 | - self.mocker.replace("landscape.configuration.bootstrap_tree")(ANY) |
69 | - self.mocker.count(0, None) |
70 | - |
71 | def get_content(self, config): |
72 | """Write C{config} to a file and return it's contents as a string.""" |
73 | config_file = self.makeFile("") |
74 | @@ -780,7 +768,11 @@ |
75 | finally: |
76 | config.config = original_config |
77 | |
78 | - def test_setup(self): |
79 | + @mock.patch("landscape.configuration.print_text") |
80 | + @mock.patch("landscape.configuration.getpass.getpass") |
81 | + @mock.patch("__builtin__.raw_input") |
82 | + def test_setup(self, mock_raw_input, mock_getpass, mock_print_text, |
83 | + mock_getuid, mock_bootstrap_tree): |
84 | filename = self.makeFile("[client]\n" |
85 | "computer_title = Old Title\n" |
86 | "account_name = Old Name\n" |
87 | @@ -792,32 +784,32 @@ |
88 | "access_group = webservers\n" |
89 | "tags = london, server") |
90 | |
91 | - raw_input = self.mocker.replace("__builtin__.raw_input", |
92 | - name="raw_input") |
93 | - getpass = self.mocker.replace("getpass.getpass") |
94 | - |
95 | - C = CONTAINS |
96 | - |
97 | - expect(raw_input(C("[Old Title]"))).result("New Title") |
98 | - expect(raw_input(C("[Old Name]"))).result("New Name") |
99 | - expect(getpass(C("Account registration key:"))).result("New Password") |
100 | - expect(getpass(C("Please confirm:"))).result("New Password") |
101 | - expect(raw_input(C("[http://old.proxy]"))).result("http://new.proxy") |
102 | - expect(raw_input(C("[https://old.proxy]"))).result("https://new.proxy") |
103 | - expect(raw_input(C("Enable script execution? [Y/n]"))).result("n") |
104 | - expect(raw_input(C("Access group [webservers]: "))).result( |
105 | - u"databases") |
106 | - expect(raw_input(C("Tags [london, server]: "))).result( |
107 | - u"glasgow, laptop") |
108 | - |
109 | - # Negative assertion. We don't want it called in any other way. |
110 | - expect(raw_input(ANY)).count(0) |
111 | - |
112 | - # We don't care about these here, but don't show any output please. |
113 | - print_text_mock = self.mocker.replace(print_text) |
114 | - expect(print_text_mock(ANY)).count(0, None) |
115 | - |
116 | - self.mocker.replay() |
117 | + def side_effect_raw_input(prompt): |
118 | + fixtures = { |
119 | + "[Old Title]": "New Title", |
120 | + "[Old Name]": "New Name", |
121 | + "[http://old.proxy]": "http://new.proxy", |
122 | + "[https://old.proxy]": "https://new.proxy", |
123 | + "Enable script execution? [Y/n]": "n", |
124 | + "Access group [webservers]: ": u"databases", |
125 | + "Tags [london, server]: ": u"glasgow, laptop", |
126 | + } |
127 | + for key, value in fixtures.iteritems(): |
128 | + if key in prompt: |
129 | + return value |
130 | + raise KeyError("Couldn't find answer for {}".format(prompt)) |
131 | + |
132 | + def side_effect_getpass(prompt): |
133 | + fixtures = {"Account registration key:": "New Password", |
134 | + "Please confirm:": "New Password"} |
135 | + for key, value in fixtures.iteritems(): |
136 | + if key in prompt: |
137 | + return value |
138 | + raise KeyError("Couldn't find answer for {}".format(prompt)) |
139 | + |
140 | + mock_raw_input.side_effect = side_effect_raw_input |
141 | + mock_getpass.side_effect = side_effect_getpass |
142 | + |
143 | config = self.get_config(["--no-start", "--config", filename]) |
144 | setup(config) |
145 | self.assertEqual(type(config), LandscapeSetupConfiguration) |
146 | @@ -834,18 +826,17 @@ |
147 | self.assertEqual(config.access_group, u"databases") |
148 | self.assertEqual(config.tags, u"glasgow, laptop") |
149 | |
150 | - def test_silent_setup(self): |
151 | + @mock.patch("landscape.configuration.SysVConfig") |
152 | + def test_silent_setup( |
153 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
154 | """ |
155 | Only command-line options are used in silent mode and registration is |
156 | attempted. |
157 | """ |
158 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
159 | - sysvconfig_mock.set_start_on_boot(True) |
160 | - sysvconfig_mock.restart_landscape() |
161 | - self.mocker.replay() |
162 | - |
163 | config = self.get_config(["--silent", "-a", "account", "-t", "rex"]) |
164 | setup(config) |
165 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
166 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
167 | self.assertConfigEqual(self.get_content(config), """\ |
168 | [client] |
169 | computer_title = rex |
170 | @@ -854,15 +845,13 @@ |
171 | url = https://landscape.canonical.com/message-system |
172 | """ % config.data_path) |
173 | |
174 | - def test_silent_setup_no_register(self): |
175 | + @mock.patch("landscape.configuration.SysVConfig") |
176 | + def test_silent_setup_no_register( |
177 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
178 | """ |
179 | Called with command line options to write a config file but no |
180 | registration or validation of parameters is attempted. |
181 | """ |
182 | - # Make sure no sysvconfig modifications are attempted |
183 | - self.mocker.patch(SysVConfig) |
184 | - self.mocker.replay() |
185 | - |
186 | config = self.get_config(["--silent", "--no-start"]) |
187 | setup(config) |
188 | self.assertConfigEqual(self.get_content(config), """\ |
189 | @@ -871,15 +860,13 @@ |
190 | url = https://landscape.canonical.com/message-system |
191 | """ % config.data_path) |
192 | |
193 | - def test_silent_setup_no_register_with_default_preseed_params(self): |
194 | + @mock.patch("landscape.configuration.SysVConfig") |
195 | + def test_silent_setup_no_register_with_default_preseed_params( |
196 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
197 | """ |
198 | Make sure that the configuration can be used to write the |
199 | configuration file after a fresh install. |
200 | """ |
201 | - # Make sure no sysvconfig modifications are attempted |
202 | - self.mocker.patch(SysVConfig) |
203 | - self.mocker.replay() |
204 | - |
205 | args = ["--silent", "--no-start", |
206 | "--computer-title", "", |
207 | "--account-name", "", |
208 | @@ -910,38 +897,31 @@ |
209 | "ping_url = http://landscape.canonical.com/ping\n" |
210 | "urgent_exchange_interval = 60\n" % config.data_path) |
211 | |
212 | - def test_silent_setup_without_computer_title(self): |
213 | + @mock.patch("landscape.configuration.SysVConfig") |
214 | + def test_silent_setup_without_computer_title( |
215 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
216 | """A computer title is required.""" |
217 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
218 | - sysvconfig_mock.set_start_on_boot(True) |
219 | - self.mocker.replay() |
220 | - |
221 | config = self.get_config(["--silent", "-a", "account"]) |
222 | self.assertRaises(ConfigurationError, setup, config) |
223 | |
224 | - def test_silent_setup_without_account_name(self): |
225 | + @mock.patch("landscape.configuration.SysVConfig") |
226 | + def test_silent_setup_without_account_name( |
227 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
228 | """An account name is required.""" |
229 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
230 | - sysvconfig_mock.set_start_on_boot(True) |
231 | - self.mocker.replay() |
232 | - |
233 | config = self.get_config(["--silent", "-t", "rex"]) |
234 | self.assertRaises(ConfigurationError, setup, config) |
235 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with( |
236 | + True) |
237 | |
238 | - def test_silent_script_users_imply_script_execution_plugin(self): |
239 | + @mock.patch("__builtin__.raw_input") |
240 | + @mock.patch("landscape.configuration.SysVConfig") |
241 | + def test_silent_script_users_imply_script_execution_plugin( |
242 | + self, mock_sysvconfig, mock_raw_input, |
243 | + mock_getuid, mock_bootstrap_tree): |
244 | """ |
245 | If C{--script-users} is specified, without C{ScriptExecution} in the |
246 | list of manager plugins, it will be automatically added. |
247 | """ |
248 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
249 | - sysvconfig_mock.set_start_on_boot(True) |
250 | - sysvconfig_mock.restart_landscape() |
251 | - self.mocker.result(True) |
252 | - |
253 | - raw_input_mock = self.mocker.replace(raw_input, passthrough=False) |
254 | - self.expect(raw_input_mock(ANY)).count(0) |
255 | - self.mocker.replay() |
256 | - |
257 | filename = self.makeFile(""" |
258 | [client] |
259 | url = https://localhost:8080/message-system |
260 | @@ -951,7 +931,12 @@ |
261 | config = self.get_config(["--config", filename, "--silent", |
262 | "-a", "account", "-t", "rex", |
263 | "--script-users", "root, nobody"]) |
264 | + mock_sysvconfig().restart_landscape.return_value = True |
265 | setup(config) |
266 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with( |
267 | + True) |
268 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
269 | + mock_raw_input.assert_not_called() |
270 | parser = ConfigParser() |
271 | parser.read(filename) |
272 | self.assertEqual( |
273 | @@ -963,15 +948,13 @@ |
274 | "account_name": "account"}, |
275 | dict(parser.items("client"))) |
276 | |
277 | - def test_silent_script_users_with_all_user(self): |
278 | + @mock.patch("landscape.configuration.SysVConfig") |
279 | + def test_silent_script_users_with_all_user( |
280 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
281 | """ |
282 | In silent mode, we shouldn't accept invalid users, it should raise a |
283 | configuration error. |
284 | """ |
285 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
286 | - sysvconfig_mock.set_start_on_boot(True) |
287 | - self.mocker.replay() |
288 | - |
289 | config = self.get_config( |
290 | ["--script-users", "all", |
291 | "--include-manager-plugins", "ScriptPlugin", |
292 | @@ -979,14 +962,13 @@ |
293 | "-t", "rex", |
294 | "--silent"]) |
295 | self.assertRaises(ConfigurationError, setup, config) |
296 | - |
297 | - def test_silent_setup_with_ping_url(self): |
298 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
299 | - sysvconfig_mock.set_start_on_boot(True) |
300 | - sysvconfig_mock.restart_landscape() |
301 | - self.mocker.result(True) |
302 | - self.mocker.replay() |
303 | - |
304 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with( |
305 | + True) |
306 | + |
307 | + @mock.patch("landscape.configuration.SysVConfig") |
308 | + def test_silent_setup_with_ping_url( |
309 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
310 | + mock_sysvconfig().restart_landscape.return_value = True |
311 | filename = self.makeFile(""" |
312 | [client] |
313 | ping_url = http://landscape.canonical.com/ping |
314 | @@ -994,10 +976,15 @@ |
315 | log_level = debug |
316 | random_key = random_value |
317 | """) |
318 | + |
319 | config = self.get_config(["--config", filename, "--silent", |
320 | "-a", "account", "-t", "rex", |
321 | "--ping-url", "http://localhost/ping"]) |
322 | setup(config) |
323 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with( |
324 | + True) |
325 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
326 | + |
327 | parser = ConfigParser() |
328 | parser.read(filename) |
329 | self.assertEqual( |
330 | @@ -1009,38 +996,35 @@ |
331 | "account_name": "account"}, |
332 | dict(parser.items("client"))) |
333 | |
334 | - def test_setup_with_proxies_from_environment(self): |
335 | + @mock.patch("landscape.configuration.LandscapeSetupScript") |
336 | + def test_setup_with_proxies_from_environment( |
337 | + self, mock_setup_script, mock_getuid, mock_bootstrap_tree): |
338 | os.environ["http_proxy"] = "http://environ" |
339 | os.environ["https_proxy"] = "https://environ" |
340 | |
341 | - script_mock = self.mocker.patch(LandscapeSetupScript) |
342 | - script_mock.run() |
343 | - |
344 | filename = self.makeFile("[client]\n" |
345 | "url = http://url\n") |
346 | |
347 | - self.mocker.replay() |
348 | - |
349 | config = self.get_config(["--no-start", "--config", filename]) |
350 | setup(config) |
351 | |
352 | # Reload it to ensure it was written down. |
353 | config.reload() |
354 | |
355 | + mock_setup_script().run.assert_called_once_with() |
356 | + |
357 | self.assertEqual(config.http_proxy, "http://environ") |
358 | self.assertEqual(config.https_proxy, "https://environ") |
359 | |
360 | - def test_silent_setup_with_proxies_from_environment(self): |
361 | + @mock.patch("landscape.configuration.SysVConfig") |
362 | + def test_silent_setup_with_proxies_from_environment( |
363 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
364 | """ |
365 | Only command-line options are used in silent mode and registration is |
366 | attempted. |
367 | """ |
368 | os.environ["http_proxy"] = "http://environ" |
369 | os.environ["https_proxy"] = "https://environ" |
370 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
371 | - sysvconfig_mock.set_start_on_boot(True) |
372 | - sysvconfig_mock.restart_landscape() |
373 | - self.mocker.replay() |
374 | |
375 | filename = self.makeFile(""" |
376 | [client] |
377 | @@ -1049,6 +1033,8 @@ |
378 | config = self.get_config(["--config", filename, "--silent", |
379 | "-a", "account", "-t", "rex"]) |
380 | setup(config) |
381 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
382 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
383 | parser = ConfigParser() |
384 | parser.read(filename) |
385 | self.assertEqual( |
386 | @@ -1059,22 +1045,20 @@ |
387 | "account_name": "account"}, |
388 | dict(parser.items("client"))) |
389 | |
390 | - def test_setup_prefers_proxies_from_config_over_environment(self): |
391 | + @mock.patch("landscape.configuration.LandscapeSetupScript") |
392 | + def test_setup_prefers_proxies_from_config_over_environment( |
393 | + self, mock_setup_script, mock_getuid, mock_bootstrap_tree): |
394 | os.environ["http_proxy"] = "http://environ" |
395 | os.environ["https_proxy"] = "https://environ" |
396 | |
397 | - script_mock = self.mocker.patch(LandscapeSetupScript) |
398 | - script_mock.run() |
399 | - |
400 | filename = self.makeFile("[client]\n" |
401 | "http_proxy = http://config\n" |
402 | "https_proxy = https://config\n" |
403 | "url = http://url\n") |
404 | |
405 | - self.mocker.replay() |
406 | - |
407 | config = self.get_config(["--no-start", "--config", filename]) |
408 | setup(config) |
409 | + mock_setup_script().run.assert_called_once_with() |
410 | |
411 | # Reload it to enusre it was written down. |
412 | config.reload() |
413 | @@ -1082,39 +1066,25 @@ |
414 | self.assertEqual(config.http_proxy, "http://config") |
415 | self.assertEqual(config.https_proxy, "https://config") |
416 | |
417 | - def test_main_no_registration(self): |
418 | - setup_mock = self.mocker.replace(setup) |
419 | - setup_mock(ANY) |
420 | - |
421 | - raw_input_mock = self.mocker.replace(raw_input) |
422 | - raw_input_mock("\nRequest a new registration for " |
423 | - "this computer now? (Y/n): ") |
424 | - self.mocker.result("n") |
425 | - |
426 | - # This must not be called. |
427 | - register_mock = self.mocker.replace(register, passthrough=False) |
428 | - register_mock(ANY, ANY) |
429 | - self.mocker.count(0) |
430 | - |
431 | - self.mocker.replay() |
432 | - |
433 | + @mock.patch("__builtin__.raw_input", return_value="n") |
434 | + @mock.patch("landscape.configuration.register") |
435 | + @mock.patch("landscape.configuration.setup") |
436 | + def test_main_no_registration( |
437 | + self, mock_setup, mock_register, mock_raw_input, mock_getuid, |
438 | + mock_bootstrap_tree): |
439 | main(["-c", self.make_working_config()], print=noop_print) |
440 | + mock_register.assert_not_called() |
441 | + mock_raw_input.assert_called_once_with( |
442 | + "\nRequest a new registration for this computer now? (Y/n): ") |
443 | |
444 | - def test_main_silent(self): |
445 | + @mock.patch("landscape.configuration.register", return_value="success") |
446 | + @mock.patch("landscape.configuration.setup") |
447 | + def test_main_silent( |
448 | + self, mock_setup, mock_register, mock_getuid, mock_bootstrap_tree): |
449 | """ |
450 | In silent mode, the client should register when the registration |
451 | details are changed/set. |
452 | """ |
453 | - setup_mock = self.mocker.replace(setup) |
454 | - setup_mock(ANY) |
455 | - |
456 | - register_mock = self.mocker.replace(register, passthrough=False) |
457 | - register_mock(ANY, ANY) |
458 | - self.mocker.result("success") |
459 | - self.mocker.count(1) |
460 | - |
461 | - self.mocker.replay() |
462 | - |
463 | config_filename = self.makeFile( |
464 | "[client]\n" |
465 | "computer_title = Old Title\n" |
466 | @@ -1126,24 +1096,16 @@ |
467 | SystemExit, main, ["-c", config_filename, "--silent"], |
468 | print=noop_print) |
469 | self.assertEqual(0, exception.code) |
470 | + mock_setup.assert_called_once_with(mock.ANY) |
471 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
472 | |
473 | - def test_main_user_interaction_success(self): |
474 | + @mock.patch("__builtin__.raw_input", return_value="y") |
475 | + @mock.patch("landscape.configuration.register", return_value="success") |
476 | + @mock.patch("landscape.configuration.setup") |
477 | + def test_main_user_interaction_success( |
478 | + self, mock_setup, mock_register, mock_raw_input, |
479 | + mock_getuid, mock_bootstrap_tree): |
480 | """The successful result of register() is communicated to the user.""" |
481 | - setup_mock = self.mocker.replace(setup) |
482 | - setup_mock(ANY) |
483 | - |
484 | - raw_input_mock = self.mocker.replace(raw_input) |
485 | - raw_input_mock("\nRequest a new registration for " |
486 | - "this computer now? (Y/n): ") |
487 | - self.mocker.result("y") |
488 | - |
489 | - # The register() function will be called. |
490 | - register_mock = self.mocker.replace(register, passthrough=False) |
491 | - register_mock(ANY, ANY) |
492 | - self.mocker.result("success") |
493 | - |
494 | - self.mocker.replay() |
495 | - |
496 | printed = [] |
497 | |
498 | def faux_print(string, file=sys.stdout): |
499 | @@ -1153,28 +1115,22 @@ |
500 | SystemExit, main, ["-c", self.make_working_config()], |
501 | print=faux_print) |
502 | self.assertEqual(0, exception.code) |
503 | + mock_setup.assert_called_once_with(mock.ANY) |
504 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
505 | + mock_raw_input.assert_called_once_with( |
506 | + "\nRequest a new registration for this computer now? (Y/n): ") |
507 | self.assertEqual( |
508 | [("Please wait...", sys.stdout), |
509 | ("System successfully registered.", sys.stdout)], |
510 | printed) |
511 | |
512 | - def test_main_user_interaction_failure(self): |
513 | + @mock.patch("__builtin__.raw_input", return_value="y") |
514 | + @mock.patch("landscape.configuration.register", return_value="failure") |
515 | + @mock.patch("landscape.configuration.setup") |
516 | + def test_main_user_interaction_failure( |
517 | + self, mock_setup, mock_register, mock_raw_input, |
518 | + mock_getuid, mock_bootstrap_tree): |
519 | """The failed result of register() is communicated to the user.""" |
520 | - setup_mock = self.mocker.replace(setup) |
521 | - setup_mock(ANY) |
522 | - |
523 | - raw_input_mock = self.mocker.replace(raw_input) |
524 | - raw_input_mock("\nRequest a new registration for " |
525 | - "this computer now? (Y/n): ") |
526 | - self.mocker.result("y") |
527 | - |
528 | - # The register() function will be called. |
529 | - register_mock = self.mocker.replace(register, passthrough=False) |
530 | - register_mock(ANY, ANY) |
531 | - self.mocker.result("failure") |
532 | - |
533 | - self.mocker.replay() |
534 | - |
535 | printed = [] |
536 | |
537 | def faux_print(string, file=sys.stdout): |
538 | @@ -1184,6 +1140,10 @@ |
539 | SystemExit, main, ["-c", self.make_working_config()], |
540 | print=faux_print) |
541 | self.assertEqual(2, exception.code) |
542 | + mock_setup.assert_called_once_with(mock.ANY) |
543 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
544 | + mock_raw_input.assert_called_once_with( |
545 | + "\nRequest a new registration for this computer now? (Y/n): ") |
546 | |
547 | # Note that the error is output via sys.stderr. |
548 | self.assertEqual( |
549 | @@ -1191,23 +1151,14 @@ |
550 | ("Invalid account name or registration key.", sys.stderr)], |
551 | printed) |
552 | |
553 | - def test_main_user_interaction_success_silent(self): |
554 | + @mock.patch("__builtin__.raw_input") |
555 | + @mock.patch("landscape.configuration.register", return_value="success") |
556 | + @mock.patch("landscape.configuration.setup") |
557 | + def test_main_user_interaction_success_silent( |
558 | + self, mock_setup, mock_register, mock_raw_input, mock_getuid, |
559 | + mock_bootstrap_tree): |
560 | """A successful result is communicated to the user even with --silent. |
561 | """ |
562 | - setup_mock = self.mocker.replace(setup) |
563 | - setup_mock(ANY) |
564 | - |
565 | - raw_input_mock = self.mocker.replace(raw_input) |
566 | - raw_input_mock(ANY) |
567 | - self.mocker.count(0) |
568 | - |
569 | - # The register() function will be called. |
570 | - register_mock = self.mocker.replace(register, passthrough=False) |
571 | - register_mock(ANY, ANY) |
572 | - self.mocker.result("success") |
573 | - |
574 | - self.mocker.replay() |
575 | - |
576 | printed = [] |
577 | |
578 | def faux_print(string, file=sys.stdout): |
579 | @@ -1217,29 +1168,23 @@ |
580 | SystemExit, main, ["--silent", "-c", self.make_working_config()], |
581 | print=faux_print) |
582 | self.assertEqual(0, exception.code) |
583 | + mock_setup.assert_called_once_with(mock.ANY) |
584 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
585 | + mock_raw_input.assert_not_called() |
586 | |
587 | self.assertEqual( |
588 | [("Please wait...", sys.stdout), |
589 | ("System successfully registered.", sys.stdout)], |
590 | printed) |
591 | |
592 | - def test_main_user_interaction_failure_silent(self): |
593 | + @mock.patch("__builtin__.raw_input") |
594 | + @mock.patch("landscape.configuration.register", return_value="failure") |
595 | + @mock.patch("landscape.configuration.setup") |
596 | + def test_main_user_interaction_failure_silent( |
597 | + self, mock_setup, mock_register, mock_raw_input, |
598 | + mock_getuid, mock_bootstrap_tree): |
599 | """A failure result is communicated to the user even with --silent. |
600 | """ |
601 | - setup_mock = self.mocker.replace(setup) |
602 | - setup_mock(ANY) |
603 | - |
604 | - raw_input_mock = self.mocker.replace(raw_input) |
605 | - raw_input_mock(ANY) |
606 | - self.mocker.count(0) |
607 | - |
608 | - # The register() function will be called. |
609 | - register_mock = self.mocker.replace(register, passthrough=False) |
610 | - register_mock(ANY, ANY) |
611 | - self.mocker.result("failure") |
612 | - |
613 | - self.mocker.replay() |
614 | - |
615 | printed = [] |
616 | |
617 | def faux_print(string, file=sys.stdout): |
618 | @@ -1249,6 +1194,9 @@ |
619 | SystemExit, main, ["--silent", "-c", self.make_working_config()], |
620 | print=faux_print) |
621 | self.assertEqual(2, exception.code) |
622 | + mock_setup.assert_called_once_with(mock.ANY) |
623 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
624 | + mock_raw_input.assert_not_called() |
625 | # Note that the error is output via sys.stderr. |
626 | self.assertEqual( |
627 | [("Please wait...", sys.stdout), |
628 | @@ -1264,198 +1212,166 @@ |
629 | "https_proxy = https://old.proxy\n" |
630 | "url = http://url\n") |
631 | |
632 | - def test_register(self): |
633 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
634 | - sysvconfig_mock.is_configured_to_run() |
635 | - self.mocker.result(False) |
636 | - sysvconfig_mock.set_start_on_boot(True) |
637 | - sysvconfig_mock.restart_landscape() |
638 | - |
639 | - script_mock = self.mocker.patch(LandscapeSetupScript) |
640 | - script_mock.run() |
641 | - |
642 | - raw_input_mock = self.mocker.replace(raw_input) |
643 | - raw_input_mock("\nRequest a new registration for " |
644 | - "this computer now? (Y/n): ") |
645 | - self.mocker.result("") |
646 | - |
647 | - raw_input_mock("\nThe Landscape client must be started " |
648 | - "on boot to operate correctly.\n\n" |
649 | - "Start Landscape client on boot? (Y/n): ") |
650 | - self.mocker.result("") |
651 | - |
652 | - register_mock = self.mocker.replace(register, passthrough=False) |
653 | - register_mock(ANY, ANY) |
654 | - |
655 | - self.mocker.replay() |
656 | + @mock.patch("__builtin__.raw_input", return_value="") |
657 | + @mock.patch("landscape.configuration.register") |
658 | + @mock.patch("landscape.configuration.LandscapeSetupScript") |
659 | + @mock.patch("landscape.configuration.SysVConfig") |
660 | + def test_register( |
661 | + self, mock_sysvconfig, mock_setup_script, mock_register, |
662 | + mock_raw_input, mock_getuid, mock_bootstrap_tree): |
663 | + mock_sysvconfig().is_configured_to_run.return_value = False |
664 | self.assertRaises( |
665 | SystemExit, main, ["--config", self.make_working_config()], |
666 | print=noop_print) |
667 | + mock_sysvconfig().is_configured_to_run.assert_called_once_with() |
668 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
669 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
670 | + mock_setup_script().run.assert_called_once_with() |
671 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
672 | + mock_raw_input.assert_any_call( |
673 | + "\nThe Landscape client must be started " |
674 | + "on boot to operate correctly.\n\n" |
675 | + "Start Landscape client on boot? (Y/n): ") |
676 | + mock_raw_input.assert_called_with( |
677 | + "\nRequest a new registration for this computer now? (Y/n): ") |
678 | |
679 | - def test_errors_from_restart_landscape(self): |
680 | + @mock.patch("landscape.configuration.print_text") |
681 | + @mock.patch("landscape.configuration.SysVConfig") |
682 | + def test_errors_from_restart_landscape( |
683 | + self, mock_sysvconfig, mock_print_text, |
684 | + mock_getuid, mock_bootstrap_tree): |
685 | """ |
686 | If a ProcessError exception is raised from restart_landscape (because |
687 | the client failed to be restarted), an informative message is printed |
688 | and the script exits. |
689 | """ |
690 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
691 | - print_text_mock = self.mocker.replace(print_text) |
692 | - |
693 | - sysvconfig_mock.set_start_on_boot(True) |
694 | - sysvconfig_mock.restart_landscape() |
695 | - self.mocker.throw(ProcessError) |
696 | - |
697 | - print_text_mock("Couldn't restart the Landscape client.", error=True) |
698 | - print_text_mock(CONTAINS("This machine will be registered"), |
699 | - error=True) |
700 | - |
701 | - self.mocker.replay() |
702 | + mock_sysvconfig().restart_landscape.side_effect = ProcessError() |
703 | |
704 | config = self.get_config(["--silent", "-a", "account", "-t", "rex"]) |
705 | system_exit = self.assertRaises(SystemExit, setup, config) |
706 | self.assertEqual(system_exit.code, 2) |
707 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
708 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
709 | + mock_print_text.assert_any_call( |
710 | + "Couldn't restart the Landscape client.", error=True) |
711 | + mock_print_text.assert_called_with( |
712 | + "This machine will be registered with the provided details when " |
713 | + "the client runs.", error=True) |
714 | |
715 | - def test_errors_from_restart_landscape_ok_no_register(self): |
716 | + @mock.patch("landscape.configuration.print_text") |
717 | + @mock.patch("landscape.configuration.SysVConfig") |
718 | + def test_errors_from_restart_landscape_ok_no_register( |
719 | + self, mock_sysvconfig, mock_print_text, |
720 | + mock_getuid, mock_bootstrap_tree): |
721 | """ |
722 | Exit code 0 will be returned if the client fails to be restarted and |
723 | --ok-no-register was passed. |
724 | """ |
725 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
726 | - print_text_mock = self.mocker.replace(print_text) |
727 | - |
728 | - sysvconfig_mock.set_start_on_boot(True) |
729 | - sysvconfig_mock.restart_landscape() |
730 | - self.mocker.throw(ProcessError) |
731 | - |
732 | - print_text_mock("Couldn't restart the Landscape client.", error=True) |
733 | - print_text_mock(CONTAINS("This machine will be registered"), |
734 | - error=True) |
735 | - |
736 | - self.mocker.replay() |
737 | + mock_sysvconfig().restart_landscape.side_effect = ProcessError() |
738 | |
739 | config = self.get_config(["--silent", "-a", "account", "-t", "rex", |
740 | "--ok-no-register"]) |
741 | system_exit = self.assertRaises(SystemExit, setup, config) |
742 | self.assertEqual(system_exit.code, 0) |
743 | - |
744 | - def test_main_with_register(self): |
745 | - setup_mock = self.mocker.replace(setup) |
746 | - setup_mock(ANY) |
747 | - raw_input_mock = self.mocker.replace(raw_input) |
748 | - raw_input_mock("\nRequest a new registration for " |
749 | - "this computer now? (Y/n): ") |
750 | - self.mocker.result("") |
751 | - |
752 | - register_mock = self.mocker.replace(register, passthrough=False) |
753 | - register_mock(ANY, ANY) |
754 | - |
755 | - self.mocker.replay() |
756 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
757 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
758 | + mock_print_text.assert_any_call( |
759 | + "Couldn't restart the Landscape client.", error=True) |
760 | + mock_print_text.assert_called_with( |
761 | + "This machine will be registered with the provided details when " |
762 | + "the client runs.", error=True) |
763 | + |
764 | + @mock.patch("__builtin__.raw_input", return_value="") |
765 | + @mock.patch("landscape.configuration.register") |
766 | + @mock.patch("landscape.configuration.setup") |
767 | + def test_main_with_register( |
768 | + self, mock_setup, mock_register, mock_raw_input, |
769 | + mock_getuid, mock_bootstrap_tree): |
770 | self.assertRaises(SystemExit, main, ["-c", self.make_working_config()], |
771 | - print=noop_print) |
772 | - |
773 | - def test_setup_init_script_and_start_client(self): |
774 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
775 | - sysvconfig_mock.set_start_on_boot(True) |
776 | - self.mocker.replay() |
777 | - |
778 | - setup_init_script_and_start_client() |
779 | - |
780 | - def test_setup_init_script_and_start_client_silent(self): |
781 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
782 | - sysvconfig_mock.set_start_on_boot(True) |
783 | - |
784 | - raw_input_mock = self.mocker.replace(raw_input, passthrough=False) |
785 | - raw_input_mock(ANY) |
786 | - self.mocker.count(0) |
787 | - self.mocker.replay() |
788 | - setup_init_script_and_start_client() |
789 | - |
790 | - def test_register_silent(self): |
791 | + print=noop_print) |
792 | + mock_setup.assert_called_once_with(mock.ANY) |
793 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
794 | + mock_raw_input.assert_called_once_with( |
795 | + "\nRequest a new registration for this computer now? (Y/n): ") |
796 | + |
797 | + @mock.patch("landscape.configuration.SysVConfig") |
798 | + def test_setup_init_script_and_start_client( |
799 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
800 | + setup_init_script_and_start_client() |
801 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
802 | + |
803 | + @mock.patch("__builtin__.raw_input") |
804 | + @mock.patch("landscape.configuration.SysVConfig") |
805 | + def test_setup_init_script_and_start_client_silent( |
806 | + self, mock_sysvconfig, mock_raw_input, |
807 | + mock_getuid, mock_bootstrap_tree): |
808 | + setup_init_script_and_start_client() |
809 | + mock_raw_input.assert_not_called() |
810 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
811 | + |
812 | + @mock.patch("__builtin__.raw_input") |
813 | + @mock.patch("landscape.configuration.register") |
814 | + @mock.patch("landscape.configuration.setup") |
815 | + def test_register_silent( |
816 | + self, mock_setup, mock_register, mock_raw_input, |
817 | + mock_getuid, mock_bootstrap_tree): |
818 | """ |
819 | Silent registration uses specified configuration to attempt a |
820 | registration with the server. |
821 | """ |
822 | - setup_mock = self.mocker.replace(setup) |
823 | - setup_mock(ANY) |
824 | - # No interaction should be requested. |
825 | - raw_input_mock = self.mocker.replace(raw_input) |
826 | - raw_input_mock(ANY) |
827 | - self.mocker.count(0) |
828 | - |
829 | - # The registration logic should be called and passed the configuration |
830 | - # file. |
831 | - register_mock = self.mocker.replace(register, passthrough=False) |
832 | - register_mock(ANY, ANY) |
833 | - |
834 | - self.mocker.replay() |
835 | - |
836 | self.assertRaises( |
837 | SystemExit, main, ["--silent", "-c", self.make_working_config()], |
838 | print=noop_print) |
839 | - |
840 | - def test_disable(self): |
841 | - stop_client_and_disable_init_script_mock = self.mocker.replace( |
842 | - stop_client_and_disable_init_script) |
843 | - stop_client_and_disable_init_script_mock() |
844 | - |
845 | - # No interaction should be requested. |
846 | - raw_input_mock = self.mocker.replace(raw_input) |
847 | - raw_input_mock(ANY) |
848 | - self.mocker.count(0) |
849 | - |
850 | - # Registration logic should not be invoked. |
851 | - register_mock = self.mocker.replace(register, passthrough=False) |
852 | - register_mock(ANY, ANY, ANY) |
853 | - self.mocker.count(0) |
854 | - |
855 | - self.mocker.replay() |
856 | - |
857 | - main(["--disable", "-c", self.make_working_config()]) |
858 | - |
859 | - def test_stop_client_and_disable_init_scripts(self): |
860 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
861 | - sysvconfig_mock.set_start_on_boot(False) |
862 | - sysvconfig_mock.stop_landscape() |
863 | - self.mocker.replay() |
864 | - |
865 | - main(["--disable", "-c", self.make_working_config()]) |
866 | - |
867 | - def test_non_root(self): |
868 | - self.mocker.reset() # Forget the thing done in setUp |
869 | - self.mocker.replace("os.getuid")() |
870 | - self.mocker.result(1000) |
871 | - self.mocker.replay() |
872 | + mock_setup.assert_called_once_with(mock.ANY) |
873 | + mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
874 | + mock_raw_input.assert_not_called() |
875 | + |
876 | + @mock.patch("__builtin__.raw_input") |
877 | + @mock.patch("landscape.configuration.register") |
878 | + @mock.patch("landscape.configuration.stop_client_and_disable_init_script") |
879 | + def test_disable( |
880 | + self, mock_stop_client, mock_register, mock_raw_input, |
881 | + mock_getuid, mock_bootstrap_tree): |
882 | + main(["--disable", "-c", self.make_working_config()]) |
883 | + mock_stop_client.assert_called_once_with() |
884 | + mock_register.assert_not_called() |
885 | + mock_raw_input.assert_not_called() |
886 | + |
887 | + @mock.patch("landscape.configuration.SysVConfig") |
888 | + def test_stop_client_and_disable_init_scripts( |
889 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
890 | + main(["--disable", "-c", self.make_working_config()]) |
891 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
892 | + mock_sysvconfig().stop_landscape.assert_called_once_with() |
893 | + |
894 | + def test_non_root(self, mock_getuid, mock_bootstrap_tree): |
895 | + mock_getuid.return_value = 1000 |
896 | sys_exit = self.assertRaises(SystemExit, |
897 | main, ["-c", self.make_working_config()]) |
898 | + mock_getuid.assert_called_once_with() |
899 | self.assertIn("landscape-config must be run as root", str(sys_exit)) |
900 | |
901 | - def test_main_with_help_and_non_root(self): |
902 | + @mock.patch("sys.stdout", new_callable=StringIO) |
903 | + def test_main_with_help_and_non_root( |
904 | + self, mock_stdout, mock_getuid, mock_bootstrap_tree): |
905 | """It's possible to call 'landscape-config --help' as normal user.""" |
906 | - self.mocker.reset() # Forget the thing done in setUp |
907 | - output = StringIO() |
908 | - self.mocker.replace("sys.stdout").write(ANY) |
909 | - self.mocker.call(output.write) |
910 | - self.mocker.replay() |
911 | + mock_getuid.return_value = 1000 |
912 | self.assertRaises(SystemExit, main, ["--help"]) |
913 | - self.assertIn("show this help message and exit", output.getvalue()) |
914 | + self.assertIn( |
915 | + "show this help message and exit", mock_stdout.getvalue()) |
916 | |
917 | - def test_main_with_help_and_non_root_short(self): |
918 | + @mock.patch("sys.stdout", new_callable=StringIO) |
919 | + def test_main_with_help_and_non_root_short( |
920 | + self, mock_stdout, mock_getuid, mock_bootstrap_tree): |
921 | """It's possible to call 'landscape-config -h' as normal user.""" |
922 | - self.mocker.reset() # Forget the thing done in setUp |
923 | - output = StringIO() |
924 | - self.mocker.replace("sys.stdout").write(ANY) |
925 | - self.mocker.call(output.write) |
926 | - self.mocker.replay() |
927 | + mock_getuid.return_value = 1000 |
928 | self.assertRaises(SystemExit, main, ["-h"]) |
929 | - self.assertIn("show this help message and exit", output.getvalue()) |
930 | - |
931 | - def test_import_from_file(self): |
932 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
933 | - sysvconfig_mock.set_start_on_boot(True) |
934 | - sysvconfig_mock.restart_landscape() |
935 | - self.mocker.result(True) |
936 | - self.mocker.replay() |
937 | - |
938 | + self.assertIn( |
939 | + "show this help message and exit", mock_stdout.getvalue()) |
940 | + |
941 | + @mock.patch("landscape.configuration.SysVConfig") |
942 | + def test_import_from_file( |
943 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
944 | configuration = ( |
945 | "[client]\n" |
946 | "computer_title = New Title\n" |
947 | @@ -1473,6 +1389,9 @@ |
948 | "--import", import_filename]) |
949 | setup(config) |
950 | |
951 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
952 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
953 | + |
954 | options = ConfigParser() |
955 | options.read(config_filename) |
956 | |
957 | @@ -1484,9 +1403,7 @@ |
958 | "https_proxy": "https://new.proxy", |
959 | "url": "http://new.url"}) |
960 | |
961 | - def test_import_from_empty_file(self): |
962 | - self.mocker.replay() |
963 | - |
964 | + def test_import_from_empty_file(self, mock_getuid, mock_bootstrap_tree): |
965 | config_filename = self.makeFile("", basename="final_config") |
966 | import_filename = self.makeFile("", basename="import_config") |
967 | |
968 | @@ -1500,9 +1417,8 @@ |
969 | else: |
970 | self.fail("ImportOptionError not raised") |
971 | |
972 | - def test_import_from_non_existent_file(self): |
973 | - self.mocker.replay() |
974 | - |
975 | + def test_import_from_non_existent_file( |
976 | + self, mock_getuid, mock_bootstrap_tree): |
977 | config_filename = self.makeFile("", basename="final_config") |
978 | import_filename = self.makeFile(basename="import_config") |
979 | |
980 | @@ -1516,9 +1432,8 @@ |
981 | else: |
982 | self.fail("ImportOptionError not raised") |
983 | |
984 | - def test_import_from_file_with_empty_client_section(self): |
985 | - self.mocker.replay() |
986 | - |
987 | + def test_import_from_file_with_empty_client_section( |
988 | + self, mock_getuid, mock_bootstrap_tree): |
989 | old_configuration = "[client]\n" |
990 | |
991 | config_filename = self.makeFile("", old_configuration, |
992 | @@ -1535,9 +1450,7 @@ |
993 | else: |
994 | self.fail("ImportOptionError not raised") |
995 | |
996 | - def test_import_from_bogus_file(self): |
997 | - self.mocker.replay() |
998 | - |
999 | + def test_import_from_bogus_file(self, mock_getuid, mock_bootstrap_tree): |
1000 | config_filename = self.makeFile("", basename="final_config") |
1001 | import_filename = self.makeFile("<strong>BOGUS!</strong>", |
1002 | basename="import_config") |
1003 | @@ -1552,12 +1465,12 @@ |
1004 | else: |
1005 | self.fail("ImportOptionError not raised") |
1006 | |
1007 | - def test_import_from_unreadable_file(self): |
1008 | + def test_import_from_unreadable_file( |
1009 | + self, mock_getuid, mock_bootstrap_tree): |
1010 | """ |
1011 | An error is raised when unable to read configuration from the |
1012 | specified file. |
1013 | """ |
1014 | - self.mocker.replay() |
1015 | import_filename = self.makeFile( |
1016 | "[client]\nfoo=bar", basename="import_config") |
1017 | # Remove read permissions |
1018 | @@ -1568,13 +1481,9 @@ |
1019 | import_filename) |
1020 | self.assertEqual(str(error), expected_message) |
1021 | |
1022 | - def test_import_from_file_preserves_old_options(self): |
1023 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
1024 | - sysvconfig_mock.set_start_on_boot(True) |
1025 | - sysvconfig_mock.restart_landscape() |
1026 | - self.mocker.result(True) |
1027 | - self.mocker.replay() |
1028 | - |
1029 | + @mock.patch("landscape.configuration.SysVConfig") |
1030 | + def test_import_from_file_preserves_old_options( |
1031 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
1032 | old_configuration = ( |
1033 | "[client]\n" |
1034 | "computer_title = Old Title\n" |
1035 | @@ -1601,6 +1510,8 @@ |
1036 | "-p", "Command Line Password"]) |
1037 | setup(config) |
1038 | |
1039 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
1040 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
1041 | options = ConfigParser() |
1042 | options.read(config_filename) |
1043 | |
1044 | @@ -1612,18 +1523,14 @@ |
1045 | "https_proxy": "https://old.proxy", |
1046 | "url": "http://new.url"}) |
1047 | |
1048 | - def test_import_from_file_may_reset_old_options(self): |
1049 | + @mock.patch("landscape.configuration.SysVConfig") |
1050 | + def test_import_from_file_may_reset_old_options( |
1051 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
1052 | """ |
1053 | This test ensures that setting an empty option in an imported |
1054 | configuration file will actually set the local value to empty |
1055 | too, rather than being ignored. |
1056 | """ |
1057 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
1058 | - sysvconfig_mock.set_start_on_boot(True) |
1059 | - sysvconfig_mock.restart_landscape() |
1060 | - self.mocker.result(True) |
1061 | - self.mocker.replay() |
1062 | - |
1063 | old_configuration = ( |
1064 | "[client]\n" |
1065 | "computer_title = Old Title\n" |
1066 | @@ -1643,6 +1550,8 @@ |
1067 | config = self.get_config(["--config", config_filename, "--silent", |
1068 | "--import", import_filename]) |
1069 | setup(config) |
1070 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
1071 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
1072 | |
1073 | options = ConfigParser() |
1074 | options.read(config_filename) |
1075 | @@ -1653,12 +1562,13 @@ |
1076 | "registration_key": "", # <== |
1077 | "url": "http://old.url"}) |
1078 | |
1079 | - def test_import_from_url(self): |
1080 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
1081 | - sysvconfig_mock.set_start_on_boot(True) |
1082 | - sysvconfig_mock.restart_landscape() |
1083 | - self.mocker.result(True) |
1084 | - |
1085 | + @mock.patch("landscape.configuration.print_text") |
1086 | + @mock.patch("landscape.configuration.fetch") |
1087 | + @mock.patch("landscape.configuration.SysVConfig") |
1088 | + def test_import_from_url( |
1089 | + self, mock_sysvconfig, mock_fetch, mock_print_text, |
1090 | + mock_getuid, mock_bootstrap_tree): |
1091 | + mock_sysvconfig().restart_landscape.return_value = True |
1092 | configuration = ( |
1093 | "[client]\n" |
1094 | "computer_title = New Title\n" |
1095 | @@ -1668,20 +1578,18 @@ |
1096 | "https_proxy = https://new.proxy\n" |
1097 | "url = http://new.url\n") |
1098 | |
1099 | - fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch") |
1100 | - fetch_mock("https://config.url") |
1101 | - self.mocker.result(configuration) |
1102 | - |
1103 | - print_text_mock = self.mocker.replace(print_text) |
1104 | - print_text_mock("Fetching configuration from https://config.url...") |
1105 | - |
1106 | - self.mocker.replay() |
1107 | + mock_fetch.return_value = configuration |
1108 | |
1109 | config_filename = self.makeFile("", basename="final_config") |
1110 | |
1111 | config = self.get_config(["--config", config_filename, "--silent", |
1112 | "--import", "https://config.url"]) |
1113 | setup(config) |
1114 | + mock_fetch.assert_called_once_with("https://config.url") |
1115 | + mock_print_text.assert_called_once_with( |
1116 | + "Fetching configuration from https://config.url...") |
1117 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
1118 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
1119 | |
1120 | options = ConfigParser() |
1121 | options.read(config_filename) |
1122 | @@ -1694,16 +1602,12 @@ |
1123 | "https_proxy": "https://new.proxy", |
1124 | "url": "http://new.url"}) |
1125 | |
1126 | - def test_import_from_url_with_http_code_fetch_error(self): |
1127 | - fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch") |
1128 | - fetch_mock("https://config.url") |
1129 | - self.mocker.throw(HTTPCodeError(501, "")) |
1130 | - |
1131 | - print_text_mock = self.mocker.replace(print_text) |
1132 | - print_text_mock("Fetching configuration from https://config.url...") |
1133 | - |
1134 | - self.mocker.replay() |
1135 | - |
1136 | + @mock.patch("landscape.configuration.print_text") |
1137 | + @mock.patch("landscape.configuration.fetch") |
1138 | + def test_import_from_url_with_http_code_fetch_error( |
1139 | + self, mock_fetch, mock_print_text, |
1140 | + mock_getuid, mock_bootstrap_tree): |
1141 | + mock_fetch.side_effect = HTTPCodeError(501, "") |
1142 | config_filename = self.makeFile("", basename="final_config") |
1143 | |
1144 | try: |
1145 | @@ -1716,16 +1620,16 @@ |
1146 | "returned HTTP code 501") |
1147 | else: |
1148 | self.fail("ImportOptionError not raised") |
1149 | - |
1150 | - def test_import_from_url_with_pycurl_error(self): |
1151 | - fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch") |
1152 | - fetch_mock("https://config.url") |
1153 | - self.mocker.throw(PyCurlError(60, "pycurl message")) |
1154 | - |
1155 | - print_text_mock = self.mocker.replace(print_text) |
1156 | - print_text_mock("Fetching configuration from https://config.url...") |
1157 | - |
1158 | - self.mocker.replay() |
1159 | + mock_fetch.assert_called_once_with("https://config.url") |
1160 | + mock_print_text.assert_called_once_with( |
1161 | + "Fetching configuration from https://config.url...") |
1162 | + |
1163 | + @mock.patch("landscape.configuration.print_text") |
1164 | + @mock.patch("landscape.configuration.fetch") |
1165 | + def test_import_from_url_with_pycurl_error( |
1166 | + self, mock_fetch, mock_print_text, |
1167 | + mock_getuid, mock_bootstrap_tree): |
1168 | + mock_fetch.side_effect = PyCurlError(60, "pycurl message") |
1169 | |
1170 | config_filename = self.makeFile("", basename="final_config") |
1171 | |
1172 | @@ -1738,17 +1642,15 @@ |
1173 | "https://config.url: Error 60: pycurl message") |
1174 | else: |
1175 | self.fail("ImportOptionError not raised") |
1176 | - |
1177 | - def test_import_from_url_with_empty_content(self): |
1178 | - fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch") |
1179 | - fetch_mock("https://config.url") |
1180 | - self.mocker.result("") |
1181 | - |
1182 | - print_text_mock = self.mocker.replace(print_text) |
1183 | - print_text_mock("Fetching configuration from https://config.url...") |
1184 | - |
1185 | - self.mocker.replay() |
1186 | - |
1187 | + mock_fetch.assert_called_once_with("https://config.url") |
1188 | + mock_print_text.assert_called_once_with( |
1189 | + "Fetching configuration from https://config.url...") |
1190 | + |
1191 | + @mock.patch("landscape.configuration.print_text") |
1192 | + @mock.patch("landscape.configuration.fetch", return_value="") |
1193 | + def test_import_from_url_with_empty_content( |
1194 | + self, mock_fetch, mock_print_text, |
1195 | + mock_getuid, mock_bootstrap_tree): |
1196 | # Use a command line option as well to test the precedence. |
1197 | try: |
1198 | self.get_config(["--silent", "--import", "https://config.url"]) |
1199 | @@ -1757,17 +1659,16 @@ |
1200 | "Nothing to import at https://config.url.") |
1201 | else: |
1202 | self.fail("ImportOptionError not raised") |
1203 | - |
1204 | - def test_import_from_url_with_bogus_content(self): |
1205 | - fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch") |
1206 | - fetch_mock("https://config.url") |
1207 | - self.mocker.result("<strong>BOGUS!</strong>") |
1208 | - |
1209 | - print_text_mock = self.mocker.replace(print_text) |
1210 | - print_text_mock("Fetching configuration from https://config.url...") |
1211 | - |
1212 | - self.mocker.replay() |
1213 | - |
1214 | + mock_fetch.assert_called_once_with("https://config.url") |
1215 | + mock_print_text.assert_called_once_with( |
1216 | + "Fetching configuration from https://config.url...") |
1217 | + |
1218 | + @mock.patch("landscape.configuration.print_text") |
1219 | + @mock.patch("landscape.configuration.fetch", |
1220 | + return_value="<strong>BOGUS!</strong>") |
1221 | + def test_import_from_url_with_bogus_content( |
1222 | + self, mock_fetch, mock_print_text, |
1223 | + mock_getuid, mock_bootstrap_tree): |
1224 | # Use a command line option as well to test the precedence. |
1225 | try: |
1226 | self.get_config(["--silent", "--import", "https://config.url"]) |
1227 | @@ -1776,45 +1677,47 @@ |
1228 | str(error)) |
1229 | else: |
1230 | self.fail("ImportOptionError not raised") |
1231 | - |
1232 | - def test_import_error_is_handled_nicely_by_main(self): |
1233 | - fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch") |
1234 | - fetch_mock("https://config.url") |
1235 | - self.mocker.throw(HTTPCodeError(404, "")) |
1236 | - |
1237 | - print_text_mock = self.mocker.replace(print_text) |
1238 | - print_text_mock("Fetching configuration from https://config.url...") |
1239 | - print_text_mock(CONTAINS("Server returned HTTP code 404"), error=True) |
1240 | - |
1241 | - self.mocker.replay() |
1242 | - |
1243 | + mock_fetch.assert_called_once_with("https://config.url") |
1244 | + mock_print_text.assert_called_once_with( |
1245 | + "Fetching configuration from https://config.url...") |
1246 | + |
1247 | + @mock.patch("landscape.configuration.print_text") |
1248 | + @mock.patch("landscape.configuration.fetch", |
1249 | + side_effect=HTTPCodeError(404, "")) |
1250 | + def test_import_error_is_handled_nicely_by_main( |
1251 | + self, mock_fetch, mock_print_text, |
1252 | + mock_getuid, mock_bootstrap_tree): |
1253 | system_exit = self.assertRaises( |
1254 | SystemExit, main, ["--import", "https://config.url"]) |
1255 | self.assertEqual(system_exit.code, 1) |
1256 | - |
1257 | - def test_base64_ssl_public_key_is_exported_to_file(self): |
1258 | - |
1259 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
1260 | - sysvconfig_mock.set_start_on_boot(True) |
1261 | - sysvconfig_mock.restart_landscape() |
1262 | - self.mocker.result(True) |
1263 | - |
1264 | + mock_fetch.assert_called_once_with("https://config.url") |
1265 | + mock_print_text.assert_any_call( |
1266 | + "Fetching configuration from https://config.url...") |
1267 | + mock_print_text.assert_called_with( |
1268 | + "Couldn't download configuration from https://config.url: " |
1269 | + "Server returned HTTP code 404", error=True) |
1270 | + |
1271 | + @mock.patch("landscape.configuration.print_text") |
1272 | + @mock.patch("landscape.configuration.SysVConfig") |
1273 | + def test_base64_ssl_public_key_is_exported_to_file( |
1274 | + self, mock_sysvconfig, mock_print_text, |
1275 | + mock_getuid, mock_bootstrap_tree): |
1276 | + mock_sysvconfig().restart_landscape.return_value = True |
1277 | data_path = self.makeDir() |
1278 | config_filename = self.makeFile("[client]\ndata_path=%s" % data_path) |
1279 | key_filename = os.path.join(data_path, |
1280 | os.path.basename(config_filename) + ".ssl_public_key") |
1281 | |
1282 | - print_text_mock = self.mocker.replace(print_text) |
1283 | - print_text_mock("Writing SSL CA certificate to %s..." % key_filename) |
1284 | - |
1285 | - self.mocker.replay() |
1286 | - |
1287 | config = self.get_config(["--silent", "-c", config_filename, |
1288 | "-u", "url", "-a", "account", "-t", "title", |
1289 | "--ssl-public-key", "base64:SGkgdGhlcmUh"]) |
1290 | config.data_path = data_path |
1291 | setup(config) |
1292 | |
1293 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
1294 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
1295 | + mock_print_text.assert_called_once_with( |
1296 | + "Writing SSL CA certificate to %s..." % key_filename) |
1297 | self.assertEqual("Hi there!", open(key_filename, "r").read()) |
1298 | |
1299 | options = ConfigParser() |
1300 | @@ -1822,13 +1725,10 @@ |
1301 | self.assertEqual(options.get("client", "ssl_public_key"), |
1302 | key_filename) |
1303 | |
1304 | - def test_normal_ssl_public_key_is_not_exported_to_file(self): |
1305 | - sysvconfig_mock = self.mocker.patch(SysVConfig) |
1306 | - sysvconfig_mock.set_start_on_boot(True) |
1307 | - sysvconfig_mock.restart_landscape() |
1308 | - self.mocker.result(True) |
1309 | - self.mocker.replay() |
1310 | - |
1311 | + @mock.patch("landscape.configuration.SysVConfig") |
1312 | + def test_normal_ssl_public_key_is_not_exported_to_file( |
1313 | + self, mock_sysvconfig, mock_getuid, mock_bootstrap_tree): |
1314 | + mock_sysvconfig().restart_landscape.return_value = True |
1315 | config_filename = self.makeFile("") |
1316 | |
1317 | config = self.get_config(["--silent", "-c", config_filename, |
1318 | @@ -1836,6 +1736,8 @@ |
1319 | "--ssl-public-key", "/some/filename"]) |
1320 | setup(config) |
1321 | |
1322 | + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) |
1323 | + mock_sysvconfig().restart_landscape.assert_called_once_with() |
1324 | key_filename = config_filename + ".ssl_public_key" |
1325 | self.assertFalse(os.path.isfile(key_filename)) |
1326 | |
1327 | @@ -1845,28 +1747,32 @@ |
1328 | "/some/filename") |
1329 | |
1330 | # We test them individually since they must work individually. |
1331 | - def test_import_from_url_honors_http_proxy(self): |
1332 | - self.ensure_import_from_url_honors_proxy_options("http_proxy") |
1333 | - |
1334 | - def test_import_from_url_honors_https_proxy(self): |
1335 | - self.ensure_import_from_url_honors_proxy_options("https_proxy") |
1336 | - |
1337 | - def ensure_import_from_url_honors_proxy_options(self, proxy_option): |
1338 | + @mock.patch("landscape.configuration.print_text") |
1339 | + @mock.patch("landscape.configuration.fetch") |
1340 | + def test_import_from_url_honors_http_proxy( |
1341 | + self, mock_fetch, mock_print_text, |
1342 | + mock_getuid, mock_bootstrap_tree): |
1343 | + self.ensure_import_from_url_honors_proxy_options( |
1344 | + "http_proxy", mock_fetch, mock_print_text) |
1345 | + |
1346 | + @mock.patch("landscape.configuration.print_text") |
1347 | + @mock.patch("landscape.configuration.fetch") |
1348 | + def test_import_from_url_honors_https_proxy( |
1349 | + self, mock_fetch, mock_print_text, |
1350 | + mock_getuid, mock_bootstrap_tree): |
1351 | + self.ensure_import_from_url_honors_proxy_options( |
1352 | + "https_proxy", mock_fetch, mock_print_text) |
1353 | + |
1354 | + def ensure_import_from_url_honors_proxy_options( |
1355 | + self, proxy_option, mock_fetch, mock_print_text): |
1356 | |
1357 | def check_proxy(url): |
1358 | + self.assertEqual("https://config.url", url) |
1359 | self.assertEqual(os.environ.get(proxy_option), "http://proxy") |
1360 | - |
1361 | - fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch") |
1362 | - fetch_mock("https://config.url") |
1363 | - self.mocker.call(check_proxy) |
1364 | - |
1365 | - # Doesn't matter. We just want to check the context around it. |
1366 | - self.mocker.result("") |
1367 | - |
1368 | - print_text_mock = self.mocker.replace(print_text) |
1369 | - print_text_mock("Fetching configuration from https://config.url...") |
1370 | - |
1371 | - self.mocker.replay() |
1372 | + # Doesn't matter. We just want to check the context around it. |
1373 | + return "" |
1374 | + |
1375 | + mock_fetch.side_effect = check_proxy |
1376 | |
1377 | config_filename = self.makeFile("", basename="final_config") |
1378 | |
1379 | @@ -1879,6 +1785,8 @@ |
1380 | pass # The returned content is empty. We don't really |
1381 | # care for this test. Mocker will ensure the tests |
1382 | # we care about are done. |
1383 | + mock_print_text.assert_called_once_with( |
1384 | + "Fetching configuration from https://config.url...") |
1385 | |
1386 | |
1387 | class FakeConnectorFactory(object): |
Command: TRIAL_ARGS=-j4 make check /ci.lscape. net/job/ latch-test/ 5087/
Result: Success
Revno: 850
Branch: lp:~adam-collard/landscape-client/mocker-replace-configuration-part-deux
Jenkins: https:/