Skip to content

Commit 4fd1810

Browse files
committed
appmenus: avoid duplicate dispvm menu updates
1 parent 9f601d8 commit 4fd1810

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

qubesappmenus/tests.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import os
2727
import tempfile
2828
import sys
29+
import types
2930

3031
import unittest
3132
import unittest.mock
@@ -35,6 +36,28 @@
3536
import qubesappmenus
3637
import qubesappmenus.receive
3738

39+
try:
40+
import qubesappmenusext
41+
except ModuleNotFoundError as e:
42+
if e.name.split('.')[0] != 'qubes':
43+
raise
44+
qubes_module = types.ModuleType('qubes')
45+
qubes_ext_module = types.ModuleType('qubes.ext')
46+
qubes_utils_module = types.ModuleType('qubes.utils')
47+
48+
def handler(*args, **kwargs):
49+
# Only decorator registration is needed for these unit tests.
50+
return lambda func: func
51+
52+
qubes_ext_module.handler = handler
53+
qubes_ext_module.Extension = object
54+
qubes_utils_module.sanitize_stderr_for_log = lambda stderr: stderr
55+
qubes_module.ext = qubes_ext_module
56+
sys.modules['qubes'] = qubes_module
57+
sys.modules['qubes.ext'] = qubes_ext_module
58+
sys.modules['qubes.utils'] = qubes_utils_module
59+
import qubesappmenusext
60+
3861
class Label(object):
3962
def __init__(self, index, color, name):
4063
self.index = index
@@ -48,6 +71,12 @@ class TestApp(object):
4871
def __init__(self):
4972
self.domains = {}
5073

74+
class TestVMM(object):
75+
offline_mode = False
76+
77+
class TestAppmenusExtApp(object):
78+
vmm = TestVMM()
79+
5180
class TestFeatures(dict):
5281

5382
def __init__(self, vm, **kwargs) -> None:
@@ -95,6 +124,18 @@ def icon(self):
95124
return 'servicevm-' + raw_icon_name
96125
return 'appvm-' + raw_icon_name
97126

127+
class TestAppmenusExtVM(object):
128+
# pylint: disable=too-few-public-methods
129+
app = TestAppmenusExtApp()
130+
131+
def __init__(self, template_for_dispvms=False,
132+
appmenus_dispvm=False):
133+
self.name = 'test-ext-vm'
134+
self.template_for_dispvms = template_for_dispvms
135+
self.features = TestFeatures(self)
136+
if appmenus_dispvm:
137+
self.features['appmenus-dispvm'] = '1'
138+
98139
VMPREFIX = 'test-'
99140

100141
class TC_00_Appmenus(unittest.TestCase):
@@ -146,6 +187,59 @@ def assertPathNotExists(self, path):
146187
if os.path.exists(path):
147188
self.fail("Path {} exists while it should not".format(path))
148189

190+
def assertUpdateScheduled(self, callback, should_schedule):
191+
ext = qubesappmenusext.AppmenusExtension()
192+
ext.collect_done_tasks = unittest.mock.Mock()
193+
ext.update_appmenus = unittest.mock.Mock(return_value='update-task')
194+
with unittest.mock.patch('asyncio.ensure_future') as ensure_future:
195+
callback(ext)
196+
if should_schedule:
197+
ext.collect_done_tasks.assert_called_once()
198+
ext.update_appmenus.assert_called_once()
199+
ensure_future.assert_called_once_with('update-task')
200+
else:
201+
ext.collect_done_tasks.assert_not_called()
202+
ext.update_appmenus.assert_not_called()
203+
ensure_future.assert_not_called()
204+
205+
def test_000_appmenus_ext_template_for_dispvms_needs_feature(self):
206+
vm = TestAppmenusExtVM(
207+
template_for_dispvms=True,
208+
appmenus_dispvm=False)
209+
210+
self.assertUpdateScheduled(
211+
lambda ext: ext.template_for_dispvms_setter(vm, None),
212+
False)
213+
214+
vm.features['appmenus-dispvm'] = '1'
215+
self.assertUpdateScheduled(
216+
lambda ext: ext.template_for_dispvms_setter(vm, None),
217+
True)
218+
219+
def test_000_appmenus_ext_dispvm_feature_needs_property(self):
220+
vm = TestAppmenusExtVM(
221+
template_for_dispvms=False,
222+
appmenus_dispvm=True)
223+
224+
self.assertUpdateScheduled(
225+
lambda ext: ext.on_feature_set_appmenus_dispvm(
226+
vm, None, 'appmenus-dispvm', '1'),
227+
False)
228+
self.assertUpdateScheduled(
229+
lambda ext: ext.on_feature_del_appmenus_dispvm(
230+
vm, None, 'appmenus-dispvm'),
231+
False)
232+
233+
vm.template_for_dispvms = True
234+
self.assertUpdateScheduled(
235+
lambda ext: ext.on_feature_set_appmenus_dispvm(
236+
vm, None, 'appmenus-dispvm', '1'),
237+
True)
238+
self.assertUpdateScheduled(
239+
lambda ext: ext.on_feature_del_appmenus_dispvm(
240+
vm, None, 'appmenus-dispvm'),
241+
True)
242+
149243

150244
def test_000_templates_dirs(self):
151245
self.assertEqual(

qubesappmenusext/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ def provides_network_setter(self, vm, event, **kwargs):
175175
def template_for_dispvms_setter(self, vm, event, **kwargs):
176176
if vm.app.vmm.offline_mode:
177177
return
178+
if not vm.features.get('appmenus-dispvm', False):
179+
return
178180
self.collect_done_tasks(vm)
179181
self.vm_tasks[vm.name].append(
180182
asyncio.ensure_future(self.update_appmenus(vm)))
@@ -194,6 +196,8 @@ def provides_network_setter(self, vm, event, name, newvalue, oldvalue=None):
194196
def on_feature_del_appmenus_dispvm(self, vm, event, feature):
195197
if vm.app.vmm.offline_mode:
196198
return
199+
if not getattr(vm, 'template_for_dispvms', False):
200+
return
197201
self.collect_done_tasks(vm)
198202
self.vm_tasks[vm.name].append(
199203
asyncio.ensure_future(self.update_appmenus(vm)))
@@ -203,6 +207,8 @@ def on_feature_set_appmenus_dispvm(self, vm, event, feature,
203207
value, oldvalue=None):
204208
if vm.app.vmm.offline_mode:
205209
return
210+
if not getattr(vm, 'template_for_dispvms', False):
211+
return
206212
self.collect_done_tasks(vm)
207213
self.vm_tasks[vm.name].append(
208214
asyncio.ensure_future(self.update_appmenus(vm)))

0 commit comments

Comments
 (0)