Merge lp:~charlesk/python-dbusmock/add-upower-device-set-properties into lp:python-dbusmock
- add-upower-device-set-properties
- Merge into trunk
Status: | Merged |
---|---|
Merge reported by: | Martin Pitt |
Merged at revision: | not available |
Proposed branch: | lp:~charlesk/python-dbusmock/add-upower-device-set-properties |
Merge into: | lp:python-dbusmock |
Diff against target: |
215 lines (+87/-29) 2 files modified
dbusmock/templates/upower.py (+48/-15) tests/test_upower.py (+39/-14) |
To merge this branch: | bzr merge lp:~charlesk/python-dbusmock/add-upower-device-set-properties |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Pitt | Approve | ||
Review via email: mp+246713@code.launchpad.net |
Commit message
Add support for changing upower device properties.
Description of the change
Add support for changing upower device properties.
Martin Pitt (pitti) wrote : | # |
Hm, this causes a test failure:
=======
FAIL: test_one_ac (test_upower.
-------
Traceback (most recent call last):
File "/home/
self.
AssertionError: Regex didn't match: 'device changed:
-------
Ran 95 tests in 14.349s
Martin Pitt (pitti) wrote : | # |
So this is genuinely broken for upower 0.99 and needs further investigation.
Charles Kerr (charlesk) wrote : | # |
Okay so the issue is that the spawned template in the unit tests is always mocking the UPower 0 API, even when UPower 0.99 is installed, so there's a disconnect between the signals that the installed "dbus --monitor" is expecting and what the dbusmock is sending.
This worked before because the signal is emitted from the unit test code (which knows the installed upower version) instead of the template (which is mocking UPower 0).
When using "dbus --monitor" to sniff for events, we need to mock the installed version of upower. So I changed the test to pass the installed version as the 'DaemonVersion' parameter when spawning the template.
This caused a couple of side-effects, test_suspend() and test_no_
So, I've moved these (and the other test_09_
- 223. By Charles Kerr
-
if a test relies on the installed version of upower, make sure to mock the installed version.
- 224. By Charles Kerr
-
fix upower.
SetDeviceProper ties' input argument signature
Charles Kerr (charlesk) : | # |
- 225. By Charles Kerr
-
silence a flake8 'too many blank lines' warning
Martin Pitt (pitti) wrote : | # |
Indeed, thanks for fixing this! I committed this to trunk: https:/
Closing MP manually as the LP branch is only a bzr mirror of the upstream git for PPA recipe purposes.
Martin Pitt (pitti) wrote : | # |
I did an upstream 0.12 release with this. Will upload to Debian experimental and then sync into vivid.
Preview Diff
1 | === modified file 'dbusmock/templates/upower.py' |
2 | --- dbusmock/templates/upower.py 2014-09-22 08:23:08 +0000 |
3 | +++ dbusmock/templates/upower.py 2015-01-16 21:21:16 +0000 |
4 | @@ -24,11 +24,13 @@ |
5 | import dbus |
6 | |
7 | from dbusmock import MOCK_IFACE, mockobject |
8 | +import dbusmock |
9 | |
10 | BUS_NAME = 'org.freedesktop.UPower' |
11 | MAIN_OBJ = '/org/freedesktop/UPower' |
12 | MAIN_IFACE = 'org.freedesktop.UPower' |
13 | SYSTEM_BUS = True |
14 | +DEVICE_IFACE = 'org.freedesktop.UPower.Device' |
15 | |
16 | |
17 | def load(mock, parameters): |
18 | @@ -59,7 +61,7 @@ |
19 | # add Display device; for defined properties, see |
20 | # http://cgit.freedesktop.org/upower/tree/src/org.freedesktop.UPower.xml |
21 | mock.AddObject(mock.p_display_dev, |
22 | - 'org.freedesktop.UPower.Device', |
23 | + DEVICE_IFACE, |
24 | { |
25 | 'Type': dbus.UInt32(0, variant_level=1), |
26 | 'State': dbus.UInt32(0, variant_level=1), |
27 | @@ -109,7 +111,7 @@ |
28 | ''' |
29 | path = '/org/freedesktop/UPower/devices/' + device_name |
30 | self.AddObject(path, |
31 | - 'org.freedesktop.UPower.Device', |
32 | + DEVICE_IFACE, |
33 | { |
34 | 'PowerSupply': dbus.Boolean(True, variant_level=1), |
35 | 'Model': dbus.String(model_name, variant_level=1), |
36 | @@ -136,7 +138,7 @@ |
37 | ''' |
38 | path = '/org/freedesktop/UPower/devices/' + device_name |
39 | self.AddObject(path, |
40 | - 'org.freedesktop.UPower.Device', |
41 | + DEVICE_IFACE, |
42 | { |
43 | 'PowerSupply': dbus.Boolean(True, variant_level=1), |
44 | 'IsPresent': dbus.Boolean(True, variant_level=1), |
45 | @@ -171,7 +173,7 @@ |
46 | ''' |
47 | path = '/org/freedesktop/UPower/devices/' + device_name |
48 | self.AddObject(path, |
49 | - 'org.freedesktop.UPower.Device', |
50 | + DEVICE_IFACE, |
51 | { |
52 | 'PowerSupply': dbus.Boolean(True, variant_level=1), |
53 | 'IsPresent': dbus.Boolean(True, variant_level=1), |
54 | @@ -209,24 +211,55 @@ |
55 | 'SetupDisplayDevice() can only be used with the 1.0 API') |
56 | |
57 | display_props = mockobject.objects[self.p_display_dev] |
58 | - display_props.Set('org.freedesktop.UPower.Device', 'Type', |
59 | + display_props.Set(DEVICE_IFACE, 'Type', |
60 | dbus.UInt32(type)) |
61 | - display_props.Set('org.freedesktop.UPower.Device', 'State', |
62 | + display_props.Set(DEVICE_IFACE, 'State', |
63 | dbus.UInt32(state)) |
64 | - display_props.Set('org.freedesktop.UPower.Device', 'Percentage', |
65 | + display_props.Set(DEVICE_IFACE, 'Percentage', |
66 | percentage) |
67 | - display_props.Set('org.freedesktop.UPower.Device', 'Energy', energy) |
68 | - display_props.Set('org.freedesktop.UPower.Device', 'EnergyFull', |
69 | + display_props.Set(DEVICE_IFACE, 'Energy', energy) |
70 | + display_props.Set(DEVICE_IFACE, 'EnergyFull', |
71 | energy_full) |
72 | - display_props.Set('org.freedesktop.UPower.Device', 'EnergyRate', |
73 | + display_props.Set(DEVICE_IFACE, 'EnergyRate', |
74 | energy_rate) |
75 | - display_props.Set('org.freedesktop.UPower.Device', 'TimeToEmpty', |
76 | + display_props.Set(DEVICE_IFACE, 'TimeToEmpty', |
77 | dbus.Int64(time_to_empty)) |
78 | - display_props.Set('org.freedesktop.UPower.Device', 'TimeToFull', |
79 | + display_props.Set(DEVICE_IFACE, 'TimeToFull', |
80 | dbus.Int64(time_to_full)) |
81 | - display_props.Set('org.freedesktop.UPower.Device', 'IsPresent', |
82 | + display_props.Set(DEVICE_IFACE, 'IsPresent', |
83 | is_present) |
84 | - display_props.Set('org.freedesktop.UPower.Device', 'IconName', |
85 | + display_props.Set(DEVICE_IFACE, 'IconName', |
86 | icon_name) |
87 | - display_props.Set('org.freedesktop.UPower.Device', 'WarningLevel', |
88 | + display_props.Set(DEVICE_IFACE, 'WarningLevel', |
89 | dbus.UInt32(warning_level)) |
90 | + |
91 | + |
92 | +@dbus.service.method(MOCK_IFACE, in_signature='oa{sv}', out_signature='') |
93 | +def SetDeviceProperties(self, object_path, properties): |
94 | + '''Convenience method to Set a device's properties. |
95 | + |
96 | + object_path: the device to update |
97 | + properties: dictionary of keys to dbus variants. |
98 | + |
99 | + If the 1.0 API is being mocked, changing this property will trigger |
100 | + the device's PropertiesChanged signal; otherwise, the older |
101 | + org.freedesktop.UPower DeviceChanged signal will be emitted. |
102 | + ''' |
103 | + device = dbusmock.get_object(object_path) |
104 | + |
105 | + # set the properties |
106 | + for key, value in properties.items(): |
107 | + device.Set(DEVICE_IFACE, key, value) |
108 | + |
109 | + # notify the listeners |
110 | + if self.api1: |
111 | + device.EmitSignal(dbus.PROPERTIES_IFACE, |
112 | + 'PropertiesChanged', |
113 | + 'sa{sv}as', |
114 | + [ |
115 | + DEVICE_IFACE, |
116 | + properties, |
117 | + [] |
118 | + ]) |
119 | + else: |
120 | + self.EmitSignal(MAIN_IFACE, 'DeviceChanged', 's', [object_path]) |
121 | |
122 | === modified file 'tests/test_upower.py' |
123 | --- tests/test_upower.py 2014-09-22 08:23:08 +0000 |
124 | +++ tests/test_upower.py 2015-01-16 21:21:16 +0000 |
125 | @@ -55,7 +55,12 @@ |
126 | |
127 | def setUp(self): |
128 | (self.p_mock, self.obj_upower) = self.spawn_server_template( |
129 | - 'upower', {'OnBattery': True, 'HibernateAllowed': False}, stdout=subprocess.PIPE) |
130 | + 'upower', { |
131 | + 'OnBattery': True, |
132 | + 'HibernateAllowed': False, |
133 | + 'DaemonVersion': upower_client_version |
134 | + }, |
135 | + stdout=subprocess.PIPE) |
136 | # set log to nonblocking |
137 | flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) |
138 | fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) |
139 | @@ -80,7 +85,6 @@ |
140 | def test_one_ac(self): |
141 | path = self.dbusmock.AddAC('mock_AC', 'Mock AC') |
142 | self.assertEqual(path, '/org/freedesktop/UPower/devices/mock_AC') |
143 | - ac_obj = self.dbus_con.get_object('org.freedesktop.UPower', path) |
144 | |
145 | self.assertRegex(self.p_mock.stdout.read(), |
146 | b'emit org.freedesktop.UPower.DeviceAdded ' |
147 | @@ -100,16 +104,9 @@ |
148 | universal_newlines=True) |
149 | |
150 | time.sleep(0.3) |
151 | - if upower_client_version < '0.99': |
152 | - # for 0.9 API |
153 | - self.dbusmock.EmitSignal('', 'DeviceChanged', 's', [path]) |
154 | - else: |
155 | - # for 1.0 API |
156 | - ac_obj.EmitSignal(dbus.PROPERTIES_IFACE, 'PropertiesChanged', 'sa{sv}as', |
157 | - dbus.Array(['org.freedesktop.UPower.Device', |
158 | - {'PowerSupply': dbus.Boolean(True, variant_level=1)}, |
159 | - dbus.Array([], signature='s')], |
160 | - signature='v')) |
161 | + self.dbusmock.SetDeviceProperties(path, { |
162 | + 'PowerSupply': dbus.Boolean(True, variant_level=1) |
163 | + }) |
164 | time.sleep(0.2) |
165 | |
166 | mon.terminate() |
167 | @@ -157,12 +154,39 @@ |
168 | self.assertRegex(out, ' time to full:\s+20.0 min') |
169 | self.assertRegex(out, ' state:\s+charging') |
170 | |
171 | + |
172 | +@unittest.skipUnless(have_upower, 'upower not installed') |
173 | +@unittest.skipUnless(upower_client_version <= '0.99', 'pre-0.99 client API specific test') |
174 | +class TestUPower0(dbusmock.DBusTestCase): |
175 | + '''Test mocking upowerd with 0.x API''' |
176 | + |
177 | + @classmethod |
178 | + def setUpClass(klass): |
179 | + klass.start_system_bus() |
180 | + klass.dbus_con = klass.get_dbus(True) |
181 | + |
182 | + def setUp(self): |
183 | + (self.p_mock, self.obj_upower) = self.spawn_server_template( |
184 | + 'upower', { |
185 | + 'OnBattery': True, |
186 | + 'HibernateAllowed': False, |
187 | + 'DaemonVersion': '0.9' |
188 | + }, |
189 | + stdout=subprocess.PIPE) |
190 | + # set log to nonblocking |
191 | + flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) |
192 | + fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) |
193 | + self.dbusmock = dbus.Interface(self.obj_upower, dbusmock.MOCK_IFACE) |
194 | + |
195 | + def tearDown(self): |
196 | + self.p_mock.terminate() |
197 | + self.p_mock.wait() |
198 | + |
199 | def test_suspend(self): |
200 | + '''0.9 API specific Suspend signal''' |
201 | self.obj_upower.Suspend(dbus_interface='org.freedesktop.UPower') |
202 | self.assertRegex(self.p_mock.stdout.readline(), b'^[0-9.]+ Suspend$') |
203 | |
204 | - @unittest.skipUnless(upower_client_version < '0.99', |
205 | - '0.9 client API specific test') |
206 | def test_09_properties(self): |
207 | '''0.9 API specific properties''' |
208 | |
209 | @@ -174,6 +198,7 @@ |
210 | self.assertNotIn('critical-action:', out) |
211 | |
212 | def test_no_display_device(self): |
213 | + '''0.9 API has no display device''' |
214 | self.assertRaises(dbus.exceptions.DBusException, |
215 | self.obj_upower.GetDisplayDevice) |
216 |
Looks good to me, with one little nitpick. Thanks!