Merge lp:~tealeg/landscape-client/ui-storage into lp:~landscape/landscape-client/trunk

Proposed by Geoff Teale
Status: Merged
Approved by: Alberto Donato
Approved revision: 482
Merged at revision: 467
Proposed branch: lp:~tealeg/landscape-client/ui-storage
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 1891 lines (+1196/-327)
12 files modified
glib-2.0/schemas/com.canonical.landscape-client-settings.gschema.xml (+37/-0)
landscape/ui/controller/configuration.py (+11/-35)
landscape/ui/controller/tests/test_configuration.py (+5/-5)
landscape/ui/lib/polkit.py (+3/-2)
landscape/ui/model/configuration/mechanism.py (+2/-1)
landscape/ui/model/configuration/proxy.py (+5/-2)
landscape/ui/model/configuration/state.py (+329/-144)
landscape/ui/model/configuration/tests/test_state.py (+458/-137)
landscape/ui/model/configuration/tests/test_uisettings.py (+189/-0)
landscape/ui/model/configuration/uisettings.py (+57/-0)
landscape/ui/tests/helpers.py (+95/-0)
setupui.py (+5/-1)
To merge this branch: bzr merge lp:~tealeg/landscape-client/ui-storage
Reviewer Review Type Date Requested Status
Alberto Donato (community) Approve
Free Ekanayaka (community) Approve
Review via email: mp+94393@code.launchpad.net

Description of the change

The second part of the fix for bug #931937,

This branch does the following:

 1. Removes the TestedGoodState and TestedBadState to reflect the decision not to tackne testing of configurations in this phase.
 2. Performs 3 stages of data setup:
     i. use code level defaults in the VirginState
     ii. overwrite user visible values with current values in GSettings (VirginState -> Initialised)
     iii. overwrite either hosted or local values from the configuration file values (VirginState -> Initialised)
 3. Persist data in two places:
     i. write all user visible data back to GSettings.
     ii. write either hosted or local values to the configuration file.

To post a comment you must log in.
Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

Great stuff, +1!

[1]

+class UISettings(object):

Please add a class docstring here.

[2]

+ def get(self, *args):

and

+ def set(self, *args):

Please add method docstrings explaining what these methods do in detail, as they seem to have non trivial logic.

[3]

+ settings = FakeGSettings(data=self.default_data)
+ uisettings = UISettings(settings)
+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)

There are a lot of these, I guess they could be moved to setUp, unless you prefer to have them there because they need slightly different parameters for each test or you like to have less context for a test.

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

Looks great! +1

Just minor stylistic notes:

#1:
+ if self._computer_title in ("", None):

you could use "if not self._computer_title" here. (there are a few of these).

#2:
+ self.assertEqual(True, state.get(IS_HOSTED))

please use assertTrue here.

#3:
+ self.config_string = "[client]\n" \

please use parentheses rather than breaking with \

+ assert(self.schema.attrib["id"] == \
+ "com.canonical.landscape-client-settings")

same here

Thanks!

review: Approve
483. By Geoff Teale

removed unused GSettings event handlers

484. By Geoff Teale

Added docstring (from Free's review)

485. By Geoff Teale

Docstring and comments on complex get/set machinary (from Free's review)

486. By Geoff Teale

Simplify empty value comparisons (from Ack's review).

487. By Geoff Teale

Replace assertEqual(True, ... with assertTrue(... (from Ack's review).

488. By Geoff Teale

Use brackets instead of line continuation (from Ack's review).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'glib-2.0'
2=== added directory 'glib-2.0/schemas'
3=== added file 'glib-2.0/schemas/com.canonical.landscape-client-settings.gschema.xml'
4--- glib-2.0/schemas/com.canonical.landscape-client-settings.gschema.xml 1970-01-01 00:00:00 +0000
5+++ glib-2.0/schemas/com.canonical.landscape-client-settings.gschema.xml 2012-02-29 16:50:20 +0000
6@@ -0,0 +1,37 @@
7+<?xml version="1.0" encoding="utf-8"?>
8+<schemalist>
9+ <schema id="com.canonical.landscape-client-settings" path="/com/canonical/landscape-client-settings/">
10+ <key type="b" name="is-hosted">
11+ <default>true</default>
12+ <summary>Whether the client settings UI currently set to a hosted client configuration.</summary>
13+ </key>
14+ <key type="s" name="computer-title">
15+ <default></default>
16+ <summary>The title to register the machine with.</summary>
17+ </key>
18+ <key type="s" name="hosted-landscape-host">
19+ <default>canonical.landscape.com</default>
20+ <summary>The hostname of the Canonical hosted landscape system.</summary>
21+ </key>
22+ <key type="s" name="hosted-account-name">
23+ <default></default>
24+ <summary>An account name for use with the Canonical hosted landscape system.</summary>
25+ </key>
26+ <key type="s" name="hosted-password">
27+ <default></default>
28+ <summary>A password for use with the Canonical hosted landscape system</summary>
29+ </key>
30+ <key type="s" name="local-landscape-host">
31+ <default></default>
32+ <summary>The hostname of the local landscape system.</summary>
33+ </key>
34+ <key type="s" name="local-account-name">
35+ <default></default>
36+ <summary>An account name for use with the local landscape system.</summary>
37+ </key>
38+ <key type="s" name="local-password">
39+ <default></default>
40+ <summary>A password for use with the local landscape system</summary>
41+ </key>
42+ </schema>
43+</schemalist>
44
45=== modified file 'landscape/ui/controller/configuration.py'
46--- landscape/ui/controller/configuration.py 2012-02-03 18:10:57 +0000
47+++ landscape/ui/controller/configuration.py 2012-02-29 16:50:20 +0000
48@@ -1,6 +1,9 @@
49 import socket
50 import threading
51 from landscape.ui.model.registration.proxy import RegistrationProxy
52+from landscape.ui.model.configuration.state import (
53+ derive_url_from_host_name, derive_ping_url_from_host_name,
54+ derive_server_host_name_from_url)
55
56
57 class ConfigControllerLockError(Exception):
58@@ -65,7 +68,7 @@
59 """
60 Default machine name to FQDN.
61 """
62- if self._computer_title is None:
63+ if self._computer_title in ("", None):
64 self._computer_title = self.getfqdn()
65
66 def default_dedicated(self):
67@@ -78,9 +81,8 @@
68 self._server_host_name = self._initial_server_host_name
69 else:
70 self._server_host_name = self.DEFAULT_SERVER_HOST_NAME
71- self._url = self._derive_url_from_host_name(
72- self._server_host_name)
73- self._ping_url = self._derive_ping_url_from_host_name(
74+ self._url = derive_url_from_host_name(self._server_host_name)
75+ self._ping_url = derive_ping_url_from_host_name(
76 self._server_host_name)
77 self.modify()
78
79@@ -91,10 +93,8 @@
80 """
81 if self._server_host_name != self.HOSTED_HOST_NAME:
82 self._server_host_name = self.HOSTED_HOST_NAME
83- self._url = self._derive_url_from_host_name(
84- self._server_host_name)
85- self._ping_url = self._derive_ping_url_from_host_name(
86- self._server_host_name)
87+ self._url = derive_url_from_host_name(self._server_host_name)
88+ self._ping_url = derive_ping_url_from_host_name(self._server_host_name)
89 self._account_name = self._initial_account_name
90 self.modify()
91
92@@ -117,7 +117,7 @@
93 self._ping_url = self._configuration.ping_url
94 if self._url:
95 self._server_host_name = \
96- self._derive_server_host_name_from_url(self._url)
97+ derive_server_host_name_from_url(self._url)
98 else:
99 self._server_host_name = self.HOSTED_HOST_NAME
100 self._initial_server_host_name = self._server_host_name
101@@ -143,29 +143,6 @@
102 self._lock.release()
103 return lock_state
104
105- def _derive_server_host_name_from_url(self, url):
106- "Extract the hostname part from a URL."
107- try:
108- without_protocol = url[url.index("://") + 3:]
109- except ValueError:
110- without_protocol = url
111- try:
112- return without_protocol[:without_protocol.index("/")]
113- except ValueError:
114- return without_protocol
115-
116- def _derive_url_from_host_name(self, host_name):
117- "Extrapolate a url from a host name."
118- #Reuse this code to make sure it's a proper host name
119- host_name = self._derive_server_host_name_from_url(host_name)
120- return "https://" + host_name + "/message-system"
121-
122- def _derive_ping_url_from_host_name(self, host_name):
123- "Extrapolate a ping_url from a host name."
124- #Reuse this code to make sure it's a proper host name
125- host_name = self._derive_server_host_name_from_url(host_name)
126- return "http://" + host_name + "/ping"
127-
128 def _get_server_host_name(self):
129 return self._server_host_name
130
131@@ -178,9 +155,8 @@
132 if value != self.HOSTED_HOST_NAME:
133 self._initial_server_host_name = value
134 self._server_host_name = value
135- self._url = self._derive_url_from_host_name(
136- self._server_host_name)
137- self._ping_url = self._derive_ping_url_from_host_name(
138+ self._url = derive_url_from_host_name(self._server_host_name)
139+ self._ping_url = derive_ping_url_from_host_name(
140 self._server_host_name)
141 self.modify()
142 self._lock.release()
143
144=== modified file 'landscape/ui/controller/tests/test_configuration.py'
145--- landscape/ui/controller/tests/test_configuration.py 2012-02-06 22:29:12 +0000
146+++ landscape/ui/controller/tests/test_configuration.py 2012-02-29 16:50:20 +0000
147@@ -224,19 +224,19 @@
148 dedicated.
149 """
150 self.controller.load()
151- self.assertEqual(None, self.controller.account_name)
152- self.assertEqual(None, self.controller.registration_password)
153+ self.assertEqual("", self.controller.account_name)
154+ self.assertEqual("", self.controller.registration_password)
155 self.assertEqual("landscape.canonical.com",
156 self.controller.server_host_name)
157 self.controller.account_name = "Bungle"
158 self.controller.default_dedicated()
159 self.assertEqual("standalone", self.controller.account_name)
160- self.assertEqual(None, self.controller.registration_password)
161+ self.assertEqual("", self.controller.registration_password)
162 self.assertEqual("landscape.localdomain",
163 self.controller.server_host_name)
164 self.controller.default_hosted()
165- self.assertEqual(None, self.controller.account_name)
166- self.assertEqual(None, self.controller.registration_password)
167+ self.assertEqual("", self.controller.account_name)
168+ self.assertEqual("", self.controller.registration_password)
169 self.assertEqual("landscape.canonical.com",
170 self.controller.server_host_name)
171 self.controller.default_dedicated()
172
173=== modified file 'landscape/ui/lib/polkit.py'
174--- landscape/ui/lib/polkit.py 2012-01-23 09:52:49 +0000
175+++ landscape/ui/lib/polkit.py 2012-02-29 16:50:20 +0000
176@@ -1,7 +1,8 @@
177 import dbus
178 import dbus.service
179 import dbus.glib
180-import gobject
181+
182+from gi.repository import GObject
183
184
185 class PolicyKitMechanism(dbus.service.Object):
186@@ -111,5 +112,5 @@
187 """
188 Invoke a L{gobject.MainLoop} to process incoming DBus events.
189 """
190- mainloop = gobject.MainLoop()
191+ mainloop = GObject.MainLoop()
192 mainloop.run()
193
194=== modified file 'landscape/ui/model/configuration/mechanism.py'
195--- landscape/ui/model/configuration/mechanism.py 2012-01-24 10:12:49 +0000
196+++ landscape/ui/model/configuration/mechanism.py 2012-02-29 16:50:20 +0000
197@@ -81,8 +81,9 @@
198 except AttributeError:
199 return ""
200 if value is None:
201- return None
202+ return ""
203 return str(value)
204+ return ""
205
206 @dbus.service.method(INTERFACE_NAME,
207 in_signature="ss",
208
209=== modified file 'landscape/ui/model/configuration/proxy.py'
210--- landscape/ui/model/configuration/proxy.py 2012-01-24 10:10:31 +0000
211+++ landscape/ui/model/configuration/proxy.py 2012-02-29 16:50:20 +0000
212@@ -22,7 +22,8 @@
213 The canonical case for this is L{landscape-client-settings-ui}.
214 """
215
216- def __init__(self, bus=None, interface=None):
217+ def __init__(self, bus=None, interface=None, loadargs=[]):
218+ self._loadargs = loadargs
219 if bus is None:
220 self._bus = dbus.SystemBus()
221 else:
222@@ -34,7 +35,9 @@
223 self._interface = interface
224
225 def load(self, arglist):
226- if arglist is None or len(arglist) == 0:
227+ if arglist is None:
228+ arglist = self._loadargs
229+ if len(arglist) == 0:
230 al = ""
231 else:
232 al = chr(0x1e).join(arglist)
233
234=== modified file 'landscape/ui/model/configuration/state.py'
235--- landscape/ui/model/configuration/state.py 2012-02-23 11:38:49 +0000
236+++ landscape/ui/model/configuration/state.py 2012-02-29 16:50:20 +0000
237@@ -1,3 +1,74 @@
238+import copy
239+import socket
240+
241+from landscape.ui.model.configuration.proxy import ConfigurationProxy
242+
243+
244+HOSTED_LANDSCAPE_HOST = "landscape.canonical.com"
245+LOCAL_LANDSCAPE_HOST = ""
246+
247+HOSTED_ACCOUNT_NAME = ""
248+LOCAL_ACCOUNT_NAME = ""
249+
250+HOSTED_PASSWORD = ""
251+LOCAL_PASSWORD = ""
252+
253+HOSTED = "hosted"
254+LOCAL = "local"
255+IS_HOSTED = "is-hosted"
256+COMPUTER_TITLE = "computer-title"
257+LANDSCAPE_HOST = "landscape-host"
258+ACCOUNT_NAME = "account-name"
259+PASSWORD = "password"
260+
261+
262+def get_fqdn():
263+ """
264+ Wrap socket.getfqdn so we can test reliably.
265+ """
266+ return socket.getfqdn()
267+
268+
269+DEFAULT_DATA = {
270+ IS_HOSTED: True,
271+ COMPUTER_TITLE: get_fqdn(),
272+ HOSTED: {
273+ LANDSCAPE_HOST: HOSTED_LANDSCAPE_HOST,
274+ ACCOUNT_NAME: HOSTED_ACCOUNT_NAME,
275+ PASSWORD: HOSTED_PASSWORD,
276+ },
277+ LOCAL: {
278+ LANDSCAPE_HOST: LOCAL_LANDSCAPE_HOST,
279+ ACCOUNT_NAME: LOCAL_ACCOUNT_NAME,
280+ PASSWORD: LOCAL_PASSWORD,
281+ }
282+}
283+
284+
285+def derive_server_host_name_from_url(url):
286+ "Extract the hostname part from a URL."
287+ try:
288+ without_protocol = url[url.index("://") + 3:]
289+ except ValueError:
290+ without_protocol = url
291+ try:
292+ return without_protocol[:without_protocol.index("/")]
293+ except ValueError:
294+ return without_protocol
295+
296+
297+def derive_url_from_host_name(host_name):
298+ "Extrapolate a url from a host name."
299+ #Reuse this code to make sure it's a proper host name
300+ host_name = derive_server_host_name_from_url(host_name)
301+ return "https://" + host_name + "/message-system"
302+
303+
304+def derive_ping_url_from_host_name(host_name):
305+ "Extrapolate a ping_url from a host name."
306+ #Reuse this code to make sure it's a proper host name
307+ host_name = derive_server_host_name_from_url(host_name)
308+ return "http://" + host_name + "/ping"
309
310
311 class StateError(Exception):
312@@ -9,15 +80,68 @@
313
314 class ConfigurationState(object):
315 """
316- Abstract base class for states used in the L{ConfigurationModel}.
317+ Base class for states used in the L{ConfigurationModel}.
318 """
319+ def __init__(self, data, proxy, uisettings):
320+ self._data = copy.deepcopy(data)
321+ self._proxy = proxy
322+ self._uisettings = uisettings
323+
324+ def get(self, *args):
325+ """
326+ Retrieve only valid values from two level dictionary based tree.
327+
328+ This mainly served to pick up programming errors and could easily be
329+ replaced with a simpler scheme.
330+ """
331+ arglen = len(args)
332+ if arglen > 2 or arglen == 0:
333+ raise TypeError(
334+ "get() takes either 1 or 2 keys (%d given)" % arglen)
335+ if arglen == 2: # We're looking for a leaf on a branch
336+ sub_dict = None
337+ if args[0] in [HOSTED, LOCAL]:
338+ sub_dict = self._data.get(args[0], {})
339+ sub_dict = self._data[args[0]]
340+ if not isinstance(sub_dict, dict):
341+ raise KeyError(
342+ "Compound key [%s][%s] is invalid. The data type " +
343+ "returned from the first index was %s." %
344+ sub_dict.__class__.__name__)
345+ return sub_dict.get(args[1], None)
346+ else: # we looking for a leaf at the root
347+ if args[0] in (IS_HOSTED, COMPUTER_TITLE):
348+ return self._data.get(args[0], None)
349+ else:
350+ raise KeyError("Key [%s] is invalid. " % args[0])
351+
352+ def set(self, *args):
353+ """
354+ Set only valid values from two level dictionary based tree.
355+
356+ This mainly served to pick up programming errors and could easily be
357+ replaced with a simpler scheme.
358+ """
359+ arglen = len(args)
360+ if arglen < 2 or arglen > 3:
361+ raise TypeError("set() takes either 1 or 2 keys and exactly 1 " +
362+ "value (%d arguments given)" % arglen)
363+ if arglen == 2: # We're setting a leaf attached to the root
364+ self._data[args[0]] = args[1]
365+ else: # We're setting a leaf on a branch
366+ sub_dict = None
367+ if args[0] in [HOSTED, LOCAL]:
368+ sub_dict = self._data.get(args[0], {})
369+ if not isinstance(sub_dict, dict):
370+ raise KeyError("Compound key [%s][%s] is invalid. The data " +
371+ "type returned from the first index was %s."
372+ % sub_dict.__class__.__name__)
373+ sub_dict[args[1]] = args[2]
374+ self._data[args[0]] = sub_dict
375
376 def load_data(self):
377 raise NotImplementedError
378
379- def test(self, test_method):
380- raise NotImplementedError
381-
382 def modify(self):
383 raise NotImplementedError
384
385@@ -28,16 +152,32 @@
386 raise NotImplementedError
387
388
389-class ModifiableHelper(object):
390+class Helper(object):
391+ """
392+ Base class for all state transition helpers.
393+
394+ It is assumed that the Helper classes are "friends" of the
395+ L{ConfigurationState} classes and can have some knowledge of their
396+ internals. They shouldn't be visible to users of the
397+ L{ConfigurationState}s and in general we should avoid seeing the
398+ L{ConfigurationState}'s _data attribute outside this module.
399+ """
400+
401+ def __init__(self, state):
402+ self._state = state
403+
404+
405+class ModifiableHelper(Helper):
406 """
407 Allow a L{ConfigurationState}s to be modified.
408 """
409
410 def modify(self):
411- return ModifiedState()
412-
413-
414-class UnloadableHelper(object):
415+ return ModifiedState(self._state._data, self._state._proxy,
416+ self._state._uisettings)
417+
418+
419+class UnloadableHelper(Helper):
420 """
421 Disallow loading of data into a L{ConfigurationModel}.
422 """
423@@ -48,7 +188,7 @@
424 " cannot be transitioned via load_data()")
425
426
427-class UnmodifiableHelper(object):
428+class UnmodifiableHelper(Helper):
429 """
430 Disallow modification of a L{ConfigurationState}.
431 """
432@@ -59,39 +199,17 @@
433 " cannot transition via modify()")
434
435
436-class TestableHelper(object):
437- """
438- Allow testing of a L{ConfigurationModel}.
439- """
440-
441- def test(self, test_method):
442- if test_method():
443- return TestedGoodState()
444- else:
445- return TestedBadState()
446-
447-
448-class UntestableHelper(object):
449- """
450- Disallow testing of a L{ConfigurationModel}.
451- """
452-
453- def test(self, test_method):
454- raise StateError("A ConfigurationModel in " +
455- self.__class__.__name__ +
456- " cannot transition via test()")
457-
458-
459-class RevertableHelper(object):
460+class RevertableHelper(Helper):
461 """
462 Allow reverting of a L{ConfigurationModel}.
463 """
464
465 def revert(self):
466- return InitialisedState()
467-
468-
469-class UnrevertableHelper(object):
470+ return InitialisedState(self._state._data, self._state._proxy,
471+ self._state._uisettings)
472+
473+
474+class UnrevertableHelper(Helper):
475 """
476 Disallow reverting of a L{ConfigurationModel}.
477 """
478@@ -102,16 +220,50 @@
479 " cannot transition via revert()")
480
481
482-class PersistableHelper(object):
483+class PersistableHelper(Helper):
484 """
485 Allow a L{ConfigurationModel} to persist.
486 """
487
488+ def _save_to_uisettings(self):
489+ self._state._uisettings.set_is_hosted(self._state.get(IS_HOSTED))
490+ self._state._uisettings.set_computer_title(
491+ self._state.get(COMPUTER_TITLE))
492+ self._state._uisettings.set_hosted_account_name(
493+ self._state.get(HOSTED, ACCOUNT_NAME))
494+ self._state._uisettings.set_hosted_password(
495+ self._state.get(HOSTED, PASSWORD))
496+ self._state._uisettings.set_local_landscape_host(
497+ self._state.get(LOCAL, LANDSCAPE_HOST))
498+ self._state._uisettings.set_local_account_name(
499+ self._state.get(LOCAL, ACCOUNT_NAME))
500+ self._state._uisettings.set_local_password(
501+ self._state.get(LOCAL, PASSWORD))
502+
503+ def _save_to_config(self):
504+ if self._state.get(IS_HOSTED):
505+ first_key = HOSTED
506+ else:
507+ first_key = LOCAL
508+ self._state._proxy.url = derive_url_from_host_name(
509+ self._state.get(first_key, LANDSCAPE_HOST))
510+ self._state._proxy.ping_url = derive_ping_url_from_host_name(
511+ self._state.get(first_key, LANDSCAPE_HOST))
512+ self._state._proxy.account_name = \
513+ self._state.get(first_key, ACCOUNT_NAME)
514+ self._state._proxy.registration_password = \
515+ self._state.get(first_key, PASSWORD)
516+ self._state._proxy.computer_title = self._state.get(COMPUTER_TITLE)
517+ self._state._proxy.write()
518+
519 def persist(self):
520- return InitialisedState()
521-
522-
523-class UnpersistableHelper(object):
524+ self._save_to_uisettings()
525+ self._save_to_config()
526+ return InitialisedState(self._state._data, self._state._proxy,
527+ self._state._uisettings)
528+
529+
530+class UnpersistableHelper(Helper):
531 """
532 Disallow persistence of a L{ConfigurationModel}.
533 """
534@@ -125,70 +277,20 @@
535 class ModifiedState(ConfigurationState):
536 """
537 The state of a L{ConfigurationModel} whenever the user has modified some
538- data but hasn't yet L{test}ed or L{revert}ed.
539- """
540-
541- _modifiable_helper = ModifiableHelper()
542- _revertable_helper = RevertableHelper()
543- _testable_helper = TestableHelper()
544- _unpersistable_helper = UnpersistableHelper()
545-
546- def modify(self):
547- return self._modifiable_helper.modify()
548-
549- def revert(self):
550- return self._revertable_helper.revert()
551-
552- def test(self, test_method):
553- return self._testable_helper.test(test_method)
554-
555- def persist(self):
556- return self._unpersistable_helper.persist()
557-
558-
559-class TestedState(ConfigurationState):
560- """
561- A superclass for the two possible L{TestedStates} (L{TestedGoodState} and
562- L{TestedBadState}).
563- """
564-
565- _untestable_helper = UntestableHelper()
566- _unloadable_helper = UnloadableHelper()
567- _modifiable_helper = ModifiableHelper()
568- _revertable_helper = RevertableHelper()
569-
570- def test(self, test_method):
571- return self._untestable_helper.test(test_method)
572-
573- def load_data(self):
574- return self._unloadable_helper.load_data()
575-
576- def modify(self):
577- return self._modifiable_helper.modify()
578-
579- def revert(self):
580- return self._revertable_helper.revert()
581-
582-
583-class TestedBadState(TestedState):
584- """
585- The state of a L{ConfigurationModel} after it has been L{test}ed but that
586- L{test} has failed for some reason.
587- """
588-
589- _unpersistable_helper = UnpersistableHelper()
590-
591- def persist(self):
592- return self._unpersistable_helper.persist()
593-
594-
595-class TestedGoodState(TestedState):
596- """
597- The state of a L{ConfigurationModel} after it has been L{test}ed
598- successfully.
599- """
600-
601- _persistable_helper = PersistableHelper()
602+ data but hasn't yet L{persist}ed or L{revert}ed.
603+ """
604+
605+ def __init__(self, data, proxy, uisettings):
606+ super(ModifiedState, self).__init__(data, proxy, uisettings)
607+ self._modifiable_helper = ModifiableHelper(self)
608+ self._revertable_helper = RevertableHelper(self)
609+ self._persistable_helper = PersistableHelper(self)
610+
611+ def modify(self):
612+ return self._modifiable_helper.modify()
613+
614+ def revert(self):
615+ return self._revertable_helper.revert()
616
617 def persist(self):
618 return self._persistable_helper.persist()
619@@ -202,10 +304,45 @@
620 finally defaults should be applied where necessary.
621 """
622
623- _modifiable_helper = ModifiableHelper()
624- _unrevertable_helper = UnrevertableHelper()
625- _testable_helper = TestableHelper()
626- _unpersistable_helper = UnpersistableHelper()
627+ def __init__(self, data, proxy, uisettings):
628+ super(InitialisedState, self).__init__(data, proxy, uisettings)
629+ self._modifiable_helper = ModifiableHelper(self)
630+ self._unrevertable_helper = UnrevertableHelper(self)
631+ self._unpersistable_helper = UnpersistableHelper(self)
632+ self._load_uisettings_data()
633+ self._load_live_data()
634+
635+ def _load_uisettings_data(self):
636+ self.set(IS_HOSTED, self._uisettings.get_is_hosted())
637+ computer_title = self._uisettings.get_computer_title()
638+ if computer_title:
639+ self.set(COMPUTER_TITLE, computer_title)
640+ self.set(HOSTED, LANDSCAPE_HOST,
641+ self._uisettings.get_hosted_landscape_host())
642+ self.set(HOSTED, ACCOUNT_NAME,
643+ self._uisettings.get_hosted_account_name())
644+ self.set(HOSTED, PASSWORD, self._uisettings.get_hosted_password())
645+ self.set(LOCAL, LANDSCAPE_HOST,
646+ self._uisettings.get_local_landscape_host())
647+ self.set(LOCAL, ACCOUNT_NAME,
648+ self._uisettings.get_local_account_name())
649+ self.set(LOCAL, PASSWORD, self._uisettings.get_local_password())
650+
651+ def _load_live_data(self):
652+ self._proxy.load(None)
653+ computer_title = self._proxy.computer_title
654+ if computer_title:
655+ self.set(COMPUTER_TITLE, computer_title)
656+ url = self._proxy.url
657+ if url.find(HOSTED_LANDSCAPE_HOST) > -1:
658+ self.set(IS_HOSTED, True)
659+ self.set(HOSTED, ACCOUNT_NAME, self._proxy.account_name)
660+ self.set(HOSTED, PASSWORD, self._proxy.registration_password)
661+ else:
662+ self.set(IS_HOSTED, False)
663+ self.set(LOCAL, LANDSCAPE_HOST,
664+ derive_server_host_name_from_url(url))
665+ self.set(LOCAL, ACCOUNT_NAME, self._proxy.account_name)
666
667 def load_data(self):
668 return self
669@@ -216,9 +353,6 @@
670 def revert(self):
671 return self._unrevertable_helper.revert()
672
673- def test(self, test_method):
674- return self._testable_helper.test(test_method)
675-
676 def persist(self):
677 return self._unpersistable_helper.persist()
678
679@@ -229,16 +363,14 @@
680 upon it.
681 """
682
683- _untestable_helper = UntestableHelper()
684- _unmodifiable_helper = UnmodifiableHelper()
685- _unrevertable_helper = UnrevertableHelper()
686- _unpersistable_helper = UnpersistableHelper()
687+ def __init__(self, proxy, uisettings):
688+ super(VirginState, self).__init__(DEFAULT_DATA, proxy, uisettings)
689+ self._unmodifiable_helper = UnmodifiableHelper(self)
690+ self._unrevertable_helper = UnrevertableHelper(self)
691+ self._unpersistable_helper = UnpersistableHelper(self)
692
693 def load_data(self):
694- return InitialisedState()
695-
696- def test(self, test_method):
697- return self._untestable_helper.test(test_method)
698+ return InitialisedState(self._data, self._proxy, self._uisettings)
699
700 def modify(self):
701 return self._unmodifiable_helper.modify()
702@@ -266,29 +398,15 @@
703
704 VirginState --(load_data)--> InitialisedState
705 InitialisedState --(modify)-----> ModifiedState
706- InitialisedState --(test)-------> TestedGoodState
707- InitialisedState --(test)-------> TestedBadState
708 ModifiedState --(revert)-----> InitialisedState
709 ModifiedState --(modify)-----> ModifiedState
710- ModifiedState --(test)-------> TestedGoodState
711- ModifiedState --(test)-------> TestedBadState
712- TestedGoodState --(revert)-----> InitialisedState
713- TestedGoodState --(persist)----> InitialisedState
714- TestedGoodState --(modify)-----> ModifiedState
715- TestedBadState --(revert)-----> InitialisedState
716- TestedBadState --(modify)-----> ModifiedState
717+ ModifiedState --(persist)----> InitialisedState
718 """
719
720- def __init__(self, test_method=None):
721- self._current_state = VirginState()
722- if test_method:
723- self._test_method = test_method
724- else:
725- self._test_method = self._test
726-
727- def _test(self):
728- # TODO, dump this and use something real
729- return True
730+ def __init__(self, proxy=None, proxy_loadargs=[], uisettings=None):
731+ if not proxy:
732+ proxy = ConfigurationProxy(loadargs=proxy_loadargs)
733+ self._current_state = VirginState(proxy, uisettings)
734
735 def get_state(self):
736 """
737@@ -299,9 +417,6 @@
738 def load_data(self):
739 self._current_state = self._current_state.load_data()
740
741- def test(self):
742- self._current_state = self._current_state.test(self._test_method)
743-
744 def modify(self):
745 self._current_state = self._current_state.modify()
746
747@@ -310,3 +425,73 @@
748
749 def persist(self):
750 self._current_state = self._current_state.persist()
751+
752+ def _get_is_hosted(self):
753+ return self._current_state.get(IS_HOSTED)
754+
755+ def _set_is_hosted(self, value):
756+ self._current_state.set(IS_HOSTED, value)
757+
758+ is_hosted = property(_get_is_hosted, _set_is_hosted)
759+
760+ def _get_computer_title(self):
761+ return self._current_state.get(COMPUTER_TITLE)
762+
763+ def _set_computer_title(self, value):
764+ self._current_state.set(COMPUTER_TITLE, value)
765+
766+ computer_title = property(_get_computer_title, _set_computer_title)
767+
768+ def _get_hosted_landscape_host(self):
769+ return self._current_state.get(HOSTED, LANDSCAPE_HOST)
770+
771+ def _set_hosted_landscape_host(self, value):
772+ self._current_state.set(HOSTED, LANDSCAPE_HOST, value)
773+
774+ hosted_landscape_host = property(_get_hosted_landscape_host,
775+ _set_hosted_landscape_host)
776+
777+ def _get_local_landscape_host(self):
778+ return self._current_state.get(LOCAL, LANDSCAPE_HOST)
779+
780+ def _set_local_landscape_host(self, value):
781+ self._current_state.set(LOCAL, LANDSCAPE_HOST, value)
782+
783+ local_landscape_host = property(_get_local_landscape_host,
784+ _set_local_landscape_host)
785+
786+ def _get_hosted_account_name(self):
787+ return self._current_state.get(HOSTED, ACCOUNT_NAME)
788+
789+ def _set_hosted_account_name(self, value):
790+ self._current_state.set(HOSTED, ACCOUNT_NAME, value)
791+
792+ hosted_account_name = property(_get_hosted_account_name,
793+ _set_hosted_account_name)
794+
795+ def _get_local_account_name(self):
796+ return self._current_state.get(LOCAL, ACCOUNT_NAME)
797+
798+ def _set_local_account_name(self, value):
799+ self._current_state.set(LOCAL, ACCOUNT_NAME, value)
800+
801+ local_account_name = property(_get_local_account_name,
802+ _set_local_account_name)
803+
804+ def _get_hosted_password(self):
805+ return self._current_state.get(HOSTED, PASSWORD)
806+
807+ def _set_hosted_password(self, value):
808+ self._current_state.set(HOSTED, PASSWORD, value)
809+
810+ hosted_password = property(_get_hosted_password,
811+ _set_hosted_password)
812+
813+ def _get_local_password(self):
814+ return self._current_state.get(LOCAL, PASSWORD)
815+
816+ def _set_local_password(self, value):
817+ self._current_state.set(LOCAL, PASSWORD, value)
818+
819+ local_password = property(_get_local_password,
820+ _set_local_password)
821
822=== modified file 'landscape/ui/model/configuration/tests/test_state.py'
823--- landscape/ui/model/configuration/tests/test_state.py 2012-02-21 10:37:58 +0000
824+++ landscape/ui/model/configuration/tests/test_state.py 2012-02-29 16:50:20 +0000
825@@ -1,7 +1,293 @@
826 from landscape.tests.helpers import LandscapeTest
827+from landscape.ui.model.configuration.uisettings import UISettings
828+import landscape.ui.model.configuration.state
829 from landscape.ui.model.configuration.state import (
830 ConfigurationModel, StateError, VirginState, InitialisedState,
831- TestedGoodState, TestedBadState, ModifiedState)
832+ ModifiedState, IS_HOSTED, HOSTED, LOCAL, HOSTED_LANDSCAPE_HOST,
833+ LANDSCAPE_HOST, COMPUTER_TITLE)
834+from landscape.ui.tests.helpers import ConfigurationProxyHelper, FakeGSettings
835+
836+
837+class ConfigurationModelTest(LandscapeTest):
838+ """
839+ Test the internal data handling of the L{ConfigurationModel} without
840+ loading external data.
841+ """
842+
843+ helpers = [ConfigurationProxyHelper]
844+
845+ default_data = {"is-hosted": True,
846+ "computer-title": "",
847+ "hosted-landscape-host": "",
848+ "hosted-account-name": "",
849+ "hosted-password": "",
850+ "local-landscape-host": "",
851+ "local-account-name": "",
852+ "local-password": ""
853+ }
854+
855+ def setUp(self):
856+ self.config_string = ""
857+ landscape.ui.model.configuration.state.DEFAULT_DATA[COMPUTER_TITLE] \
858+ = "bound.to.lose"
859+ super(ConfigurationModelTest, self).setUp()
860+
861+ def tearDown(self):
862+ super(ConfigurationModelTest, self).tearDown()
863+ self.proxy = None
864+
865+ def test_get(self):
866+ """
867+ Test that L{get} correctly extracts data from the internal data storage
868+ of the L{ConfigurationState}s associated with a L{ConfigurationModel}.
869+ """
870+ settings = FakeGSettings(data=self.default_data)
871+ uisettings = UISettings(settings)
872+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
873+ state = model.get_state()
874+ self.assertTrue(state.get(IS_HOSTED))
875+ self.assertEqual(HOSTED_LANDSCAPE_HOST,
876+ state.get(HOSTED, LANDSCAPE_HOST))
877+ self.assertRaises(TypeError, state.get, IS_HOSTED, HOSTED,
878+ LANDSCAPE_HOST)
879+ self.assertRaises(KeyError, state.get, LANDSCAPE_HOST)
880+ self.assertRaises(KeyError, state.get, IS_HOSTED, LANDSCAPE_HOST)
881+
882+ def test_set(self):
883+ """
884+ Test that L{set} correctly sets data in the internal data storage of
885+ the L{ConfigurationState}s associated with a L{ConfigurationModel}.
886+ """
887+ settings = FakeGSettings(data=self.default_data)
888+ uisettings = UISettings(settings)
889+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
890+ state = model.get_state()
891+ state.set(IS_HOSTED, True)
892+ self.assertTrue(state.get(IS_HOSTED))
893+ state.set(IS_HOSTED, False)
894+ self.assertFalse(state.get(IS_HOSTED))
895+ self.assertEqual("", state.get(LOCAL, LANDSCAPE_HOST))
896+ state.set(LOCAL, LANDSCAPE_HOST, "goodison.park")
897+ self.assertEqual("goodison.park", state.get(LOCAL, LANDSCAPE_HOST))
898+
899+ def test_virginal(self):
900+ """
901+ Test that the L{ConfigurationModel} is created with default data. This
902+ should be managed via L{VirginState} (hence the name), but this should
903+ not be exposed and is not explicitly tested here (see
904+ L{StateTransitionTest}).
905+ """
906+ settings = FakeGSettings(data=self.default_data)
907+ uisettings = UISettings(settings)
908+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
909+ self.assertTrue(model.is_hosted)
910+ self.assertEqual(HOSTED_LANDSCAPE_HOST, model.hosted_landscape_host)
911+ self.assertEqual("bound.to.lose", model.computer_title)
912+ self.assertEqual("", model.local_landscape_host)
913+ self.assertEqual("", model.hosted_account_name)
914+ self.assertEqual("", model.local_account_name)
915+ self.assertEqual("", model.hosted_password)
916+
917+ def test_is_hosted_property(self):
918+ """
919+ Test we can use the L{is_hosted} property to set and get that data on
920+ the current L{ConfigurationState}.
921+ """
922+ settings = FakeGSettings(data=self.default_data)
923+ uisettings = UISettings(settings)
924+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
925+ model.load_data()
926+ self.assertTrue(model.is_hosted)
927+ model.is_hosted = False
928+ self.assertFalse(model.is_hosted)
929+
930+ def test_computer_title_property(self):
931+ """
932+ Test that we can use the L{computer_title} property to set and get that
933+ data on the current L{ConfigurationState}.
934+ """
935+ settings = FakeGSettings(data=self.default_data)
936+ uisettings = UISettings(settings)
937+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
938+ model.load_data()
939+ self.assertEqual("bound.to.lose", model.computer_title)
940+ model.computer_title = "bound.to.win"
941+ self.assertEqual("bound.to.win", model.computer_title)
942+
943+ def test_hosted_landscape_host_property(self):
944+ """
945+ Test we can use the L{hosted_landscape_host} property to set and get
946+ that data on the current L{ConfigurationState}.
947+ """
948+ settings = FakeGSettings(data=self.default_data)
949+ uisettings = UISettings(settings)
950+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
951+ self.assertEqual(HOSTED_LANDSCAPE_HOST, model.hosted_landscape_host)
952+ model.hosted_landscape_host = "foo"
953+ self.assertEqual("foo", model.hosted_landscape_host)
954+
955+ def test_hosted_account_name_property(self):
956+ """
957+ Test we can use the L{hosted_account_name} property to set and get
958+ that data on the current L{ConfigurationState}.
959+ """
960+ settings = FakeGSettings(data=self.default_data)
961+ uisettings = UISettings(settings)
962+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
963+ self.assertEqual("", model.hosted_account_name)
964+ model.hosted_account_name = "foo"
965+ self.assertEqual("foo", model.hosted_account_name)
966+
967+ def test_hosted_password_property(self):
968+ """
969+ Test we can use the L{hosted_password} property to set and get
970+ that data on the current L{ConfigurationState}.
971+ """
972+ settings = FakeGSettings(data=self.default_data)
973+ uisettings = UISettings(settings)
974+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
975+ self.assertEqual("", model.hosted_password)
976+ model.hosted_password = "foo"
977+ self.assertEqual("foo", model.hosted_password)
978+
979+ def test_local_landscape_host_property(self):
980+ """
981+ Test we can use the L{local_landscape_host} property to set and get
982+ that data on the current L{ConfigurationState}.
983+ """
984+ settings = FakeGSettings(data=self.default_data)
985+ uisettings = UISettings(settings)
986+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
987+ self.assertEqual("", model.local_landscape_host)
988+ model.local_landscape_host = "foo"
989+ self.assertEqual("foo", model.local_landscape_host)
990+
991+ def test_local_account_name_property(self):
992+ """
993+ Test we can use the L{local_account_name} property to set and get
994+ that data on the current L{ConfigurationState}.
995+ """
996+ settings = FakeGSettings(data=self.default_data)
997+ uisettings = UISettings(settings)
998+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
999+ self.assertEqual("", model.local_account_name)
1000+ model.local_account_name = "foo"
1001+ self.assertEqual("foo", model.local_account_name)
1002+
1003+ def test_local_password_property(self):
1004+ """
1005+ Test we can use the L{local_password} property to set and get
1006+ that data on the current L{ConfigurationState}.
1007+ """
1008+ settings = FakeGSettings(data=self.default_data)
1009+ uisettings = UISettings(settings)
1010+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1011+ self.assertEqual("", model.local_password)
1012+ model.local_password = "foo"
1013+ self.assertEqual("foo", model.local_password)
1014+
1015+
1016+class ConfigurationModelHostedTest(LandscapeTest):
1017+ """
1018+ Test the L{ConfigurationModel} is correctly initialised when the live
1019+ configuration is set for a hosted account.
1020+
1021+ Note the multilayer data loading:
1022+
1023+ 1. Internal state is defaulted.
1024+ 2. UISettings data is loaded.
1025+ 3. Live configuration is loaded.
1026+ """
1027+
1028+ helpers = [ConfigurationProxyHelper]
1029+
1030+ default_data = {"is-hosted": True,
1031+ "computer-title": "bound.to.lose",
1032+ "hosted-landscape-host": "landscape.canonical.com",
1033+ "hosted-account-name": "Sparklehorse",
1034+ "hosted-password": "Vivadixiesubmarinetransmissionplot",
1035+ "local-landscape-host": "the.local.machine",
1036+ "local-account-name": "CrazyHorse",
1037+ "local-password": "RustNeverSleeps"
1038+ }
1039+
1040+ def setUp(self):
1041+ self.config_string = "[client]\n" \
1042+ "data_path = /var/lib/landscape/client/\n" \
1043+ "http_proxy = http://proxy.localdomain:3192\n" \
1044+ "tags = a_tag\n" \
1045+ "url = https://landscape.canonical.com/message-system\n" \
1046+ "account_name = foo\n" \
1047+ "registration_password = boink\n" \
1048+ "computer_title = baz\n" \
1049+ "https_proxy = https://proxy.localdomain:6192\n" \
1050+ "ping_url = http://landscape.canonical.com/ping\n"
1051+
1052+ super(ConfigurationModelHostedTest, self).setUp()
1053+
1054+ def test_initialised_hosted(self):
1055+ """
1056+ Test the L{ConfigurationModel} is correctly initialised from a proxy
1057+ and defaults with hosted data.
1058+ """
1059+ settings = FakeGSettings(data=self.default_data)
1060+ uisettings = UISettings(settings)
1061+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1062+ model.load_data()
1063+ self.assertTrue(model.is_hosted)
1064+ self.assertEqual("landscape.canonical.com",
1065+ model.hosted_landscape_host)
1066+ self.assertEqual("the.local.machine", model.local_landscape_host)
1067+ self.assertEqual("foo", model.hosted_account_name)
1068+ self.assertEqual("CrazyHorse", model.local_account_name)
1069+ self.assertEqual("boink", model.hosted_password)
1070+
1071+
1072+class ConfigurationModelLocalTest(LandscapeTest):
1073+
1074+ helpers = [ConfigurationProxyHelper]
1075+
1076+ default_data = {"is-hosted": True,
1077+ "computer-title": "bound.to.lose",
1078+ "hosted-landscape-host": "landscape.canonical.com",
1079+ "hosted-account-name": "Sparklehorse",
1080+ "hosted-password": "Vivadixiesubmarinetransmissionplot",
1081+ "local-landscape-host": "the.local.machine",
1082+ "local-account-name": "CrazyHorse",
1083+ "local-password": "RustNeverSleeps"
1084+ }
1085+
1086+ def setUp(self):
1087+ self.config_string = "[client]\n" \
1088+ "data_path = /var/lib/landscape/client/\n" \
1089+ "http_proxy = http://proxy.localdomain:3192\n" \
1090+ "tags = a_tag\n" \
1091+ "url = https://landscape.localdomain/message-system\n" \
1092+ "account_name = foo\n" \
1093+ "registration_password = boink\n" \
1094+ "computer_title = baz\n" \
1095+ "https_proxy = \n" \
1096+ "ping_url = http://landscape.localdomain/ping\n"
1097+
1098+ super(ConfigurationModelLocalTest, self).setUp()
1099+
1100+ def test_initialised_local(self):
1101+ """
1102+ Test the L{ConfigurationModel} is correctly initialised from a proxy
1103+ and defaults with local data.
1104+ """
1105+ settings = FakeGSettings(data=self.default_data)
1106+ uisettings = UISettings(settings)
1107+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1108+ model.load_data()
1109+ self.assertFalse(model.is_hosted)
1110+ self.assertEqual("landscape.canonical.com",
1111+ model.hosted_landscape_host)
1112+ self.assertEqual("landscape.localdomain", model.local_landscape_host)
1113+ self.assertEqual("Sparklehorse", model.hosted_account_name)
1114+ self.assertEqual("foo", model.local_account_name)
1115+ self.assertEqual("Vivadixiesubmarinetransmissionplot",
1116+ model.hosted_password)
1117
1118
1119 class StateTransitionTest(LandscapeTest):
1120@@ -10,12 +296,30 @@
1121 L{ConfigurationModel}.
1122 """
1123
1124+ helpers = [ConfigurationProxyHelper]
1125+
1126+ def setUp(self):
1127+ self.config_string = ""
1128+ self.default_data = {
1129+ "is-hosted": True,
1130+ "computer-title": "bound.to.lose",
1131+ "hosted-landscape-host": "landscape.canonical.com",
1132+ "hosted-account-name": "Sparklehorse",
1133+ "hosted-password": "Vivadixiesubmarinetransmissionplot",
1134+ "local-landscape-host": "the.local.machine",
1135+ "local-account-name": "CrazyHorse",
1136+ "local-password": "RustNeverSleeps"
1137+ }
1138+ super(StateTransitionTest, self).setUp()
1139+
1140 def test_load_data_transitions(self):
1141 """
1142 Test that the L{ConfigurationModel} correctly changes state as we call
1143 L{load_data}.
1144 """
1145- model = ConfigurationModel()
1146+ settings = FakeGSettings(data=self.default_data)
1147+ uisettings = UISettings(settings)
1148+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1149 self.assertTrue(isinstance(model.get_state(), VirginState))
1150 model.load_data()
1151 self.assertTrue(isinstance(model.get_state(), InitialisedState))
1152@@ -24,54 +328,14 @@
1153 self.assertTrue(isinstance(model.get_state(), InitialisedState))
1154 self.assertIs(initialised, model.get_state())
1155
1156- def test_testing_a_virgin_raises(self):
1157- """
1158- Test that calling L{test} on a L{ConfigurationModel} in L{VirginState}
1159- raises an error.
1160- """
1161- model = ConfigurationModel()
1162- self.assertTrue(isinstance(model.get_state(), VirginState))
1163- self.assertRaises(StateError, model.test)
1164-
1165- def test_load_data_on_tested_state_raises(self):
1166- """
1167- Test that calling L{load_data} on a L{ConfigurationModel} in either one
1168- of the two L{TestedState} subclasses (L{TestedGoodState} or
1169- L{TestedBadState}) will raise a L{StateError}.
1170- """
1171- test_succeed = lambda: True
1172- test_fail = lambda: False
1173- model = ConfigurationModel(test_method=test_succeed)
1174- model.load_data()
1175- model.test()
1176- self.assertRaises(StateError, model.load_data)
1177- model = ConfigurationModel(test_method=test_fail)
1178- model.load_data()
1179- model.test()
1180- self.assertRaises(StateError, model.load_data)
1181-
1182- def test_test_transition(self):
1183- """
1184- Test that the L{ConfigurationModel} transitions to a L{TestedGoodState}
1185- or a L{TestedBadState} when L{test} is called.
1186- """
1187- test_succeed = lambda: True
1188- test_fail = lambda: False
1189- model = ConfigurationModel(test_method=test_succeed)
1190- model.load_data()
1191- model.test()
1192- self.assertTrue(isinstance(model.get_state(), TestedGoodState))
1193- model = ConfigurationModel(test_method=test_fail)
1194- model.load_data()
1195- model.test()
1196- self.assertTrue(isinstance(model.get_state(), TestedBadState))
1197-
1198 def test_modifying_a_virgin_raises(self):
1199 """
1200 Test that attempting a L{modify} a L{ConfigurationModel} in
1201 L{VirginState} raises a L{StateError}.
1202 """
1203- model = ConfigurationModel()
1204+ settings = FakeGSettings(data=self.default_data)
1205+ uisettings = UISettings(settings)
1206+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1207 self.assertRaises(StateError, model.modify)
1208
1209 def test_initialised_state_is_modifiable(self):
1210@@ -79,50 +343,28 @@
1211 Test that the L{ConfigurationModel} transitions to L{ModifiedState}
1212 whenever L{modify} is called on it in L{InitialisedState}.
1213 """
1214- model = ConfigurationModel()
1215+ settings = FakeGSettings(data=self.default_data)
1216+ uisettings = UISettings(settings)
1217+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1218 model.load_data()
1219+ self.assertTrue(model.is_hosted)
1220+ model.is_hosted = False
1221+ self.assertFalse(model.is_hosted)
1222 model.modify()
1223 self.assertTrue(isinstance(model.get_state(), ModifiedState))
1224+ self.assertFalse(model.is_hosted)
1225
1226 def test_modified_state_is_modifiable(self):
1227 """
1228 Test that the L{ConfigurationModel} transitions to L{ModifiedState}
1229 whenever L{modify} is called on it in L{ModifiedState}.
1230 """
1231- model = ConfigurationModel()
1232- model.load_data()
1233- model.modify()
1234- self.assertTrue(isinstance(model.get_state(), ModifiedState))
1235- model.modify()
1236- self.assertTrue(isinstance(model.get_state(), ModifiedState))
1237-
1238- def test_modified_state_is_testable(self):
1239- """
1240- Test that the L{ConfigurationModel} can be transitioned via L{test}
1241- when it is in the L{ModifiedState}.
1242- """
1243- model = ConfigurationModel()
1244- model.load_data()
1245- model.modify()
1246- model.test()
1247- self.assertTrue(isinstance(model.get_state(), TestedGoodState))
1248-
1249- def test_tested_states_are_modifiable(self):
1250- """
1251- Test that the L{ConfigurationModel} transitions to L{ModifiedState}
1252- whenever L{modify} is called on it in a subclass of L{TestedState}
1253- (L{TestedGoodState} or L{TestedBadState}).
1254- """
1255- test_succeed = lambda: True
1256- test_fail = lambda: False
1257- model = ConfigurationModel(test_method=test_succeed)
1258- model.load_data()
1259- model.test()
1260- model.modify()
1261- self.assertTrue(isinstance(model.get_state(), ModifiedState))
1262- model = ConfigurationModel(test_method=test_fail)
1263- model.load_data()
1264- model.test()
1265+ settings = FakeGSettings(data=self.default_data)
1266+ uisettings = UISettings(settings)
1267+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1268+ model.load_data()
1269+ model.modify()
1270+ self.assertTrue(isinstance(model.get_state(), ModifiedState))
1271 model.modify()
1272 self.assertTrue(isinstance(model.get_state(), ModifiedState))
1273
1274@@ -131,7 +373,9 @@
1275 Test that calling L{revert} on a L{ConfigurationModel} in
1276 L{VirginState} raises a L{StateError}.
1277 """
1278- model = ConfigurationModel()
1279+ settings = FakeGSettings(data=self.default_data)
1280+ uisettings = UISettings(settings)
1281+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1282 self.assertRaises(StateError, model.revert)
1283
1284 def test_initialiased_state_is_unrevertable(self):
1285@@ -139,7 +383,9 @@
1286 Test that calling L{revert} on a L{ConfigurationModel} in
1287 L{InitialisedState} raises a L{StateError}.
1288 """
1289- model = ConfigurationModel()
1290+ settings = FakeGSettings(data=self.default_data)
1291+ uisettings = UISettings(settings)
1292+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1293 model.load_data()
1294 self.assertRaises(StateError, model.revert)
1295
1296@@ -148,36 +394,43 @@
1297 Test that a L{ConfigurationModel} in L{ModifiedState} can be
1298 transitioned via L{revert} to L{InitialisedState}.
1299 """
1300- model = ConfigurationModel()
1301+ settings = FakeGSettings(data=self.default_data)
1302+ uisettings = UISettings(settings)
1303+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1304 model.load_data()
1305 model.modify()
1306 model.revert()
1307 self.assertTrue(isinstance(model.get_state(), InitialisedState))
1308
1309- def test_tested_states_are_revertable(self):
1310- """
1311- Test that a L{ConfigurationModel} in one of the two L{TestedState}s can
1312- be transitioned via L{revert} to L{InitialisedState}.
1313- """
1314- test_succeed = lambda: True
1315- test_fail = lambda: False
1316- model = ConfigurationModel(test_method=test_succeed)
1317- model.load_data()
1318- model.test()
1319- model.revert()
1320- self.assertTrue(isinstance(model.get_state(), InitialisedState))
1321- model = ConfigurationModel(test_method=test_fail)
1322- model.load_data()
1323- model.test()
1324- model.revert()
1325- self.assertTrue(isinstance(model.get_state(), InitialisedState))
1326+ def test_reverting_reverts_data(self):
1327+ """
1328+ Test that transitioning via L{revert} causes the original
1329+ L{InitialisedState} to be restored.
1330+ """
1331+ settings = FakeGSettings(data=self.default_data)
1332+ uisettings = UISettings(settings)
1333+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1334+ model.load_data()
1335+ self.assertEqual(HOSTED_LANDSCAPE_HOST, model.hosted_landscape_host)
1336+ self.assertEqual("CrazyHorse", model.local_account_name)
1337+ model.hosted_landscape_host = "foo"
1338+ model.local_account_name = "bar"
1339+ model.modify()
1340+ self.assertEqual("foo", model.hosted_landscape_host)
1341+ self.assertEqual("bar", model.local_account_name)
1342+ model.revert()
1343+ self.assertTrue(isinstance(model.get_state(), InitialisedState))
1344+ self.assertEqual(HOSTED_LANDSCAPE_HOST, model.hosted_landscape_host)
1345+ self.assertEqual("CrazyHorse", model.local_account_name)
1346
1347 def test_persisting_a_virgin_raises(self):
1348 """
1349 Test that a L{ConfigurationModel} in L{VirginState} will raise a
1350 L{StateError} when you attempt to transition it with L{persist}.
1351 """
1352- model = ConfigurationModel()
1353+ settings = FakeGSettings(data=self.default_data)
1354+ uisettings = UISettings(settings)
1355+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1356 self.assertRaises(StateError, model.persist)
1357
1358 def test_persisting_initialised_state_raises(self):
1359@@ -185,39 +438,107 @@
1360 Test that a L{ConfigurationModel} in L{IntialisedState} will raise a
1361 L{StateError} when you attempt to transition it with L{persist}.
1362 """
1363- model = ConfigurationModel()
1364- model.load_data()
1365- self.assertRaises(StateError, model.persist)
1366-
1367- def test_persisting_modified_state_raises(self):
1368- """
1369- Test that a L{ConfigurationModel} in L{InitialisedState} will raise a
1370- L{StateError} when you attempt to transition it with L{persist}.
1371- """
1372- model = ConfigurationModel()
1373- model.load_data()
1374- model.modify()
1375- self.assertRaises(StateError, model.persist)
1376-
1377- def test_persisting_tested_bad_state_raises(self):
1378- """
1379- Test that a L{ConfigurationModel} in L{TestedBadState} will raise a
1380- L{StateError} when you attempt to transition it with L{persist}.
1381- """
1382- test_fail = lambda: False
1383- model = ConfigurationModel(test_method=test_fail)
1384- model.load_data()
1385- model.test()
1386- self.assertRaises(StateError, model.persist)
1387-
1388- def test_persist_tested_good_state(self):
1389- """
1390- Test that a L{ConfigurationModel} in L{TestedGoodState} can be
1391- transitioned via L{persist} to a L{IntialisedState}.
1392- """
1393- test_succeed = lambda: True
1394- model = ConfigurationModel(test_method=test_succeed)
1395- model.load_data()
1396- model.test()
1397- model.persist()
1398- self.assertTrue(isinstance(model.get_state(), InitialisedState))
1399+ settings = FakeGSettings(data=self.default_data)
1400+ uisettings = UISettings(settings)
1401+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1402+ model.load_data()
1403+ self.assertRaises(StateError, model.persist)
1404+
1405+ def test_persisting_modified_is_allowed(self):
1406+ """
1407+ Test that a L{ConfigurationModel} in L{ModifiedState} will allow itself
1408+ to be transitioned with L{persist}.
1409+ """
1410+ settings = FakeGSettings(data=self.default_data)
1411+ uisettings = UISettings(settings)
1412+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1413+ model.load_data()
1414+ model.modify()
1415+ model.persist()
1416+ self.assertTrue(isinstance(model.get_state(), InitialisedState))
1417+
1418+ def test_persisting_saves_data_to_uisettings(self):
1419+ settings = FakeGSettings(data=self.default_data)
1420+ uisettings = UISettings(settings)
1421+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1422+ model.load_data()
1423+ self.assertTrue(uisettings.get_is_hosted())
1424+ self.assertEqual("Sparklehorse", uisettings.get_hosted_account_name())
1425+ self.assertEqual("Vivadixiesubmarinetransmissionplot",
1426+ uisettings.get_hosted_password())
1427+ self.assertEqual("the.local.machine",
1428+ uisettings.get_local_landscape_host())
1429+ self.assertEqual("CrazyHorse", uisettings.get_local_account_name())
1430+ self.assertEqual("RustNeverSleeps", uisettings.get_local_password())
1431+ model.is_hosted = False
1432+ model.hosted_account_name = "ThomasPaine"
1433+ model.hosted_password = "TheAgeOfReason"
1434+ model.local_landscape_host = "another.local.machine"
1435+ model.local_account_name = "ThomasHobbes"
1436+ model.local_password = "TheLeviathan"
1437+ model.modify()
1438+ self.assertTrue(isinstance(model.get_state(), ModifiedState))
1439+ model.persist()
1440+ self.assertTrue(isinstance(model.get_state(), InitialisedState))
1441+ self.assertFalse(uisettings.get_is_hosted())
1442+ self.assertEqual("ThomasPaine", uisettings.get_hosted_account_name())
1443+ self.assertEqual("TheAgeOfReason", uisettings.get_hosted_password())
1444+ self.assertEqual("another.local.machine",
1445+ uisettings.get_local_landscape_host())
1446+ self.assertEqual("ThomasHobbes", uisettings.get_local_account_name())
1447+ self.assertEqual("TheLeviathan", uisettings.get_local_password())
1448+
1449+
1450+class StateTransitionWithExistingConfigTest(LandscapeTest):
1451+ """
1452+ Test that we handle existing configuration data correctly when
1453+ transitioning through L{ConfigurationModel} states.
1454+ """
1455+
1456+ helpers = [ConfigurationProxyHelper]
1457+
1458+ def setUp(self):
1459+ self.config_string = (
1460+ "[client]\n"
1461+ "data_path = /var/lib/landscape/client/\n"
1462+ "http_proxy = http://proxy.localdomain:3192\n"
1463+ "tags = a_tag\n"
1464+ "url = https://landscape.canonical.com/message-system\n"
1465+ "account_name = Sparklehorse\n"
1466+ "registration_password = Vivadixiesubmarinetransmissionplot\n"
1467+ "computer_title = baz\n"
1468+ "https_proxy = https://proxy.localdomain:6192\n"
1469+ "ping_url = http://landscape.canonical.com/ping\n")
1470+ self.default_data = {
1471+ "is-hosted": True,
1472+ "computer-title": "bound.to.lose",
1473+ "hosted-landscape-host": "landscape.canonical.com",
1474+ "hosted-account-name": "Sparklehorse",
1475+ "hosted-password": "Vivadixiesubmarinetransmissionplot",
1476+ "local-landscape-host": "the.local.machine",
1477+ "local-account-name": "CrazyHorse",
1478+ "local-password": "RustNeverSleeps"
1479+ }
1480+ super(StateTransitionWithExistingConfigTest, self).setUp()
1481+
1482+ def test_persisting_saves_data_to_proxy(self):
1483+ settings = FakeGSettings(data=self.default_data)
1484+ uisettings = UISettings(settings)
1485+ model = ConfigurationModel(proxy=self.proxy, uisettings=uisettings)
1486+ model.load_data()
1487+ self.assertEqual("Sparklehorse", self.proxy.account_name)
1488+ self.assertEqual("Vivadixiesubmarinetransmissionplot",
1489+ self.proxy.registration_password)
1490+ model.is_hosted = False
1491+ model.local_account_name = "ThomasPaine"
1492+ model.local_password = "TheAgeOfReason"
1493+ model.modify()
1494+ self.assertTrue(isinstance(model.get_state(), ModifiedState))
1495+ model.persist()
1496+ self.assertTrue(isinstance(model.get_state(), InitialisedState))
1497+ self.assertFalse(model.is_hosted)
1498+ self.assertEqual("https://the.local.machine/message-system",
1499+ self.proxy.url)
1500+ self.assertEqual("http://the.local.machine/ping", self.proxy.ping_url)
1501+ self.assertEqual("ThomasPaine", self.proxy.account_name)
1502+ self.assertEqual("TheAgeOfReason", self.proxy.registration_password)
1503
1504=== added file 'landscape/ui/model/configuration/tests/test_uisettings.py'
1505--- landscape/ui/model/configuration/tests/test_uisettings.py 1970-01-01 00:00:00 +0000
1506+++ landscape/ui/model/configuration/tests/test_uisettings.py 2012-02-29 16:50:20 +0000
1507@@ -0,0 +1,189 @@
1508+from landscape.tests.helpers import LandscapeTest
1509+from landscape.ui.tests.helpers import FakeGSettings
1510+from landscape.ui.model.configuration.uisettings import UISettings
1511+
1512+
1513+class UISettingsTest(LandscapeTest):
1514+
1515+ default_data = {"is-hosted": True,
1516+ "computer-title": "bound.to.lose",
1517+ "hosted-landscape-host": "landscape.canonical.com",
1518+ "hosted-account-name": "Sparklehorse",
1519+ "hosted-password": "Vivadixiesubmarinetransmissionplot",
1520+ "local-landscape-host": "the.local.machine",
1521+ "local-account-name": "CrazyHorse",
1522+ "local-password": "RustNeverSleeps"
1523+ }
1524+
1525+ def test_setup(self):
1526+ """
1527+ Test that the L{GSettings.Client} is correctly initialised.
1528+ """
1529+ settings = FakeGSettings(data=self.default_data)
1530+ UISettings(settings)
1531+ self.assertTrue(settings.was_called_with_args(
1532+ "new", UISettings.BASE_KEY))
1533+
1534+ def test_get_is_hosted(self):
1535+ """
1536+ Test that the L{get_is_hosted} value is correctly fetched from the
1537+ L{GSettings.Client}.
1538+ """
1539+ settings = FakeGSettings(data=self.default_data)
1540+ uisettings = UISettings(settings)
1541+ self.assertTrue(uisettings.get_is_hosted())
1542+
1543+ def test_set_is_hosted(self):
1544+ """
1545+ Test that we can correctly use L{set_is_hosted} to write the
1546+ L{is_hosted} value to the L{GSettings.Client}.
1547+ """
1548+ settings = FakeGSettings(data=self.default_data)
1549+ uisettings = UISettings(settings)
1550+ self.assertTrue(uisettings.get_is_hosted())
1551+ uisettings.set_is_hosted(False)
1552+ self.assertFalse(uisettings.get_is_hosted())
1553+ self.assertTrue(settings.was_called_with_args(
1554+ "set_boolean", "is-hosted", False))
1555+
1556+ def test_get_computer_title(self):
1557+ """
1558+ Test that the L{get_computer_title} value is correctly fetched
1559+ from the L{GSettings.Client}.
1560+ """
1561+ settings = FakeGSettings(data=self.default_data)
1562+ uisettings = UISettings(settings)
1563+ self.assertEqual("bound.to.lose",
1564+ uisettings.get_computer_title())
1565+
1566+ def test_set_computer_title(self):
1567+ """
1568+ Test that L{set_computer_title} correctly sets the value of
1569+ L{computer_title} in the L{GSettings.Client}.
1570+ """
1571+ settings = FakeGSettings(data=self.default_data)
1572+ uisettings = UISettings(settings)
1573+ self.assertEqual("bound.to.lose", uisettings.get_computer_title())
1574+ uisettings.set_computer_title("Bang")
1575+ self.assertEqual("Bang", uisettings.get_computer_title())
1576+
1577+ def test_get_hosted_landscape_host(self):
1578+ """
1579+ Test that the L{get_hosted_landscape_host} value is correctly fetched
1580+ from the L{GSettings.Client}.
1581+ """
1582+ settings = FakeGSettings(data=self.default_data)
1583+ uisettings = UISettings(settings)
1584+ self.assertEqual("landscape.canonical.com",
1585+ uisettings.get_hosted_landscape_host())
1586+
1587+ # NOTE: There is no facility to set the hosted-landscape-host
1588+
1589+ def test_get_hosted_account_name(self):
1590+ """
1591+ Test that the L{get_hosted_account_name} value is correctly fetched
1592+ from the L{GSettings.Client}.
1593+ """
1594+ settings = FakeGSettings(data=self.default_data)
1595+ uisettings = UISettings(settings)
1596+ self.assertEqual("Sparklehorse",
1597+ uisettings.get_hosted_account_name())
1598+
1599+ def test_set_hosted_account_name(self):
1600+ """
1601+ Test that L{set_hosted_account_name} correctly sets the value of
1602+ L{hosted_account_name} in the L{GSettings.Client}.
1603+ """
1604+ settings = FakeGSettings(data=self.default_data)
1605+ uisettings = UISettings(settings)
1606+ self.assertEqual("Sparklehorse", uisettings.get_hosted_account_name())
1607+ uisettings.set_hosted_account_name("Bang")
1608+ self.assertEqual("Bang", uisettings.get_hosted_account_name())
1609+
1610+ def test_get_hosted_password(self):
1611+ """
1612+ Test that the L{get_hosted_password} value is correctly fetched
1613+ from the L{GSettings.Client}.
1614+ """
1615+ settings = FakeGSettings(data=self.default_data)
1616+ uisettings = UISettings(settings)
1617+ self.assertEqual("Vivadixiesubmarinetransmissionplot",
1618+ uisettings.get_hosted_password())
1619+
1620+ def test_set_hosted_password(self):
1621+ """
1622+ Test that L{set_hosted_password} correctly sets the value of
1623+ L{hosted_password} in the L{GSettings.Client}.
1624+ """
1625+ settings = FakeGSettings(data=self.default_data)
1626+ uisettings = UISettings(settings)
1627+ self.assertEqual("Vivadixiesubmarinetransmissionplot",
1628+ uisettings.get_hosted_password())
1629+ uisettings.set_hosted_password("Bang")
1630+ self.assertEqual("Bang", uisettings.get_hosted_password())
1631+
1632+ def test_get_local_landscape_host(self):
1633+ """
1634+ Test that the L{get_local_landscape_host} value is correctly fetched
1635+ from the L{GSettings.Client}.
1636+ """
1637+ settings = FakeGSettings(data=self.default_data)
1638+ uisettings = UISettings(settings)
1639+ self.assertEqual("the.local.machine",
1640+ uisettings.get_local_landscape_host())
1641+
1642+ def test_set_local_landscape_host(self):
1643+ """
1644+ Test that L{set_local_landscape_host} correctly sets the value of
1645+ L{local_landscape_host} in the L{GSettings.Client}.
1646+ """
1647+ settings = FakeGSettings(data=self.default_data)
1648+ uisettings = UISettings(settings)
1649+ self.assertEqual("the.local.machine",
1650+ uisettings.get_local_landscape_host())
1651+ uisettings.set_local_landscape_host("Bang")
1652+ self.assertEqual("Bang", uisettings.get_local_landscape_host())
1653+
1654+ def test_get_local_account_name(self):
1655+ """
1656+ Test that the L{get_local_account_name} value is correctly fetched
1657+ from the L{GSettings.Client}.
1658+ """
1659+ settings = FakeGSettings(data=self.default_data)
1660+ uisettings = UISettings(settings)
1661+ self.assertEqual("CrazyHorse",
1662+ uisettings.get_local_account_name())
1663+
1664+ def test_set_local_account_name(self):
1665+ """
1666+ Test that L{set_local_account_name} correctly sets the value of
1667+ L{local_account_name} in the L{GSettings.Client}.
1668+ """
1669+ settings = FakeGSettings(data=self.default_data)
1670+ uisettings = UISettings(settings)
1671+ self.assertEqual("CrazyHorse",
1672+ uisettings.get_local_account_name())
1673+ uisettings.set_local_account_name("Bang")
1674+ self.assertEqual("Bang", uisettings.get_local_account_name())
1675+
1676+ def test_get_local_password(self):
1677+ """
1678+ Test that the L{get_local_password} value is correctly fetched
1679+ from the L{GSettings.Client}.
1680+ """
1681+ settings = FakeGSettings(data=self.default_data)
1682+ uisettings = UISettings(settings)
1683+ self.assertEqual("RustNeverSleeps",
1684+ uisettings.get_local_password())
1685+
1686+ def test_set_local_password(self):
1687+ """
1688+ Test that L{set_local_password} correctly sets the value of
1689+ L{local_password} in the L{GSettings.Client}.
1690+ """
1691+ settings = FakeGSettings(data=self.default_data)
1692+ uisettings = UISettings(settings)
1693+ self.assertEqual("RustNeverSleeps",
1694+ uisettings.get_local_password())
1695+ uisettings.set_local_password("Bang")
1696+ self.assertEqual("Bang", uisettings.get_local_password())
1697
1698=== added file 'landscape/ui/model/configuration/uisettings.py'
1699--- landscape/ui/model/configuration/uisettings.py 1970-01-01 00:00:00 +0000
1700+++ landscape/ui/model/configuration/uisettings.py 2012-02-29 16:50:20 +0000
1701@@ -0,0 +1,57 @@
1702+class UISettings(object):
1703+ """
1704+ A very thin wrapper around L{GSettings} to avoid having to know the
1705+ L{BaseKey} and type information elsewhere. In some future version it would
1706+ be right to bind to change events here so we can react to people changing
1707+ the settings in dconf, for now that is overkill.
1708+ """
1709+
1710+ BASE_KEY = "com.canonical.landscape-client-settings"
1711+
1712+ def __init__(self, settings):
1713+ self.settings = settings.new(self.BASE_KEY)
1714+
1715+ def get_is_hosted(self):
1716+ return self.settings.get_boolean("is-hosted")
1717+
1718+ def set_is_hosted(self, value):
1719+ self.settings.set_boolean("is-hosted", value)
1720+
1721+ def get_computer_title(self):
1722+ return self.settings.get_string("computer-title")
1723+
1724+ def set_computer_title(self, value):
1725+ self.settings.set_string("computer-title", value)
1726+
1727+ def get_hosted_landscape_host(self):
1728+ return self.settings.get_string("hosted-landscape-host")
1729+
1730+ def get_hosted_account_name(self):
1731+ return self.settings.get_string("hosted-account-name")
1732+
1733+ def set_hosted_account_name(self, value):
1734+ self.settings.set_string("hosted-account-name", value)
1735+
1736+ def get_hosted_password(self):
1737+ return self.settings.get_string("hosted-password")
1738+
1739+ def set_hosted_password(self, value):
1740+ self.settings.set_string("hosted-password", value)
1741+
1742+ def get_local_landscape_host(self):
1743+ return self.settings.get_string("local-landscape-host")
1744+
1745+ def set_local_landscape_host(self, value):
1746+ self.settings.set_string("local-landscape-host", value)
1747+
1748+ def get_local_account_name(self):
1749+ return self.settings.get_string("local-account-name")
1750+
1751+ def set_local_account_name(self, value):
1752+ self.settings.set_string("local-account-name", value)
1753+
1754+ def get_local_password(self):
1755+ return self.settings.get_string("local-password")
1756+
1757+ def set_local_password(self, value):
1758+ self.settings.set_string("local-password", value)
1759
1760=== modified file 'landscape/ui/tests/helpers.py'
1761--- landscape/ui/tests/helpers.py 2012-01-26 12:40:16 +0000
1762+++ landscape/ui/tests/helpers.py 2012-02-29 16:50:20 +0000
1763@@ -1,3 +1,6 @@
1764+import os
1765+
1766+from lxml import etree
1767 import dbus
1768
1769 from landscape.configuration import LandscapeSetupConfiguration
1770@@ -50,3 +53,95 @@
1771 def tear_down(self, test_case):
1772 if not dbus_test_should_skip:
1773 test_case.mechanism.remove_from_connection()
1774+
1775+
1776+class FakeGSettings(object):
1777+ """
1778+ This class impersonates a real L{gi.repostiroy.Gio.GSettings}
1779+ object to allow for testing code that utilises it without setting values in
1780+ the live DConf.
1781+ """
1782+
1783+ calls = {}
1784+
1785+ def __init__(self, data={}):
1786+ self.set_data(data)
1787+ tree = etree.parse(
1788+ os.path.join(
1789+ os.path.dirname(os.path.abspath(__file__)),
1790+ "../../../",
1791+ "glib-2.0/schemas/",
1792+ "com.canonical.landscape-client-settings.gschema.xml"))
1793+ root = tree.getroot()
1794+ self.schema = root.find("schema")
1795+ assert(self.schema.attrib["id"] ==
1796+ "com.canonical.landscape-client-settings")
1797+ self.keys = {}
1798+ for key in self.schema.findall("key"):
1799+ self.keys[key.attrib["name"]] = key.attrib["type"]
1800+
1801+ def check_key_data(self, name, gstype):
1802+ if name in self.keys:
1803+ if self.keys[name] == gstype:
1804+ return True
1805+ else:
1806+ raise ValueError("The GSchema file says %s is a %s, " +
1807+ "but you asked for a %s" %
1808+ (name, self.keys[name], gstype))
1809+ else:
1810+ raise KeyError("Can't find %s in the GSchema file!" % name)
1811+
1812+ def get_value(self, name, gstype):
1813+ if self.check_key_data(name, gstype):
1814+ return self.data[name]
1815+
1816+ def set_value(self, name, gstype, value):
1817+ if self.check_key_data(name, gstype):
1818+ self.data[name] = value
1819+
1820+ def set_data(self, data):
1821+ self.data = data
1822+
1823+ def _call(self, name, *args):
1824+ [count, arglist] = self.calls.get(name, (0, []))
1825+ count += 1
1826+ arglist.append(self._args_to_string(*args))
1827+ self.calls[name] = [count, arglist]
1828+
1829+ def _args_to_string(self, *args):
1830+ return "|".join([str(arg) for arg in args])
1831+
1832+ def new(self, key):
1833+ self._call("new", key)
1834+ return self
1835+
1836+ def connect(self, signal, callback, *args):
1837+ self._call("connect", signal, callback, *args)
1838+
1839+ def get_boolean(self, name):
1840+ self._call("get_boolean", name)
1841+ return self.get_value(name, "b")
1842+
1843+ def set_boolean(self, name, value):
1844+ self._call("set_boolean", name, value)
1845+ self.set_value(name, "b", value)
1846+
1847+ def get_string(self, name):
1848+ self._call("get_string", name)
1849+ return self.get_value(name, "s")
1850+
1851+ def set_string(self, name, value):
1852+ self._call("set_string", name, value)
1853+ self.set_value(name, "s", value)
1854+
1855+ def was_called(self, name):
1856+ return self.calls.haskey(name)
1857+
1858+ def was_called_with_args(self, name, *args):
1859+ try:
1860+ [count, arglist] = self.calls.get(name, (0, []))
1861+ except KeyError:
1862+ return False
1863+
1864+ expected_args = self._args_to_string(*args)
1865+ return expected_args in arglist
1866
1867=== modified file 'scripts/landscape-client-registration-mechanism' (properties changed: -x to +x)
1868=== modified file 'scripts/landscape-client-settings-mechanism' (properties changed: -x to +x)
1869=== modified file 'setupui.py'
1870--- setupui.py 2012-01-19 14:06:45 +0000
1871+++ setupui.py 2012-02-29 16:50:20 +0000
1872@@ -39,6 +39,7 @@
1873 ff = open(service_path, "w")
1874 ff.write(output)
1875 ff.close()
1876+ os.system("glib-compile-schemas /usr/share/glib-2.0/schemas/")
1877
1878
1879 pkit_description = \
1880@@ -76,7 +77,10 @@
1881 ('/usr/share/applications/',
1882 ['applications/landscape-client-settings.desktop']),
1883 ('/usr/share/icons/hicolor/scalable/apps/',
1884- ['icons/preferences-management-service.svg'])],
1885+ ['icons/preferences-management-service.svg']),
1886+ ('/usr/share/glib-2.0/schemas/',
1887+ ['glib-2.0/schemas/com.canonical.landscape-client-settings.gschema.xml'])
1888+ ],
1889 scripts=['scripts/landscape-client-settings-mechanism',
1890 'scripts/landscape-client-registration-mechanism',
1891 "scripts/landscape-client-settings-ui"],

Subscribers

People subscribed via source and target branches

to all changes: