Skip to content

Commit 094af98

Browse files
committed
q-dev: updated tests and wait for attachment to be done
1 parent a80d27d commit 094af98

File tree

3 files changed

+53
-42
lines changed

3 files changed

+53
-42
lines changed

qubesusbproxy/core3ext.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,12 @@ async def on_domain_start(self, vm, _event, **_kwargs):
711711
if device not in to_attach:
712712
# make it unique
713713
to_attach[device] = assignment.clone(device=device)
714+
in_progress = set()
714715
for assignment in to_attach.values():
715-
asyncio.ensure_future(self.attach_and_notify(vm, assignment))
716+
in_progress.add(
717+
asyncio.ensure_future(self.attach_and_notify(vm, assignment)))
718+
if in_progress:
719+
await asyncio.wait(in_progress)
716720

717721
@qubes.ext.handler('domain-shutdown')
718722
async def on_domain_shutdown(self, vm, _event, **_kwargs):

qubesusbproxy/tests.py

+48-40
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#
2424
import unittest
2525
from unittest import mock
26-
from unittest.mock import Mock
26+
from unittest.mock import Mock, AsyncMock
2727

2828
import jinja2
2929

@@ -40,10 +40,10 @@
4040
try:
4141
from qubes.device_protocol import DeviceAssignment, VirtualDevice, Port
4242

43-
def make_assignment(backend, ident, required=False):
43+
def make_assignment(backend, ident, auto_attach=False):
4444
return DeviceAssignment(VirtualDevice(Port(
4545
backend, ident, 'usb')),
46-
mode='required' if required else 'manual')
46+
mode='auto-attach' if auto_attach else 'manual')
4747

4848
def assign(test, collection, assignment):
4949
test.loop.run_until_complete(collection.assign(assignment))
@@ -401,7 +401,8 @@ def setUp(self):
401401
self.qrexec_policy('qubes.USB', self.frontend.name, self.backend.name)
402402
self.usbdev_ident = create_usb_gadget(self.backend).decode()
403403
self.usbdev_name = '{}:{}:{}'.format(
404-
self.backend.name, self.usbdev_ident, "0000:0000::?******")
404+
self.backend.name, self.usbdev_ident,
405+
"1234:1234:0123456789:u080650")
405406

406407
def tearDown(self):
407408
# remove vms in this specific order, otherwise there may remain stray
@@ -416,9 +417,7 @@ def test_000_list(self):
416417

417418
def test_010_assign(self):
418419
usb_dev = self.backend.devices['usb'][self.usbdev_ident]
419-
ass = DeviceAssignment(VirtualDevice(Port(
420-
self.backend, self.usbdev_ident, 'usb')),
421-
mode='ask-to-attach')
420+
ass = make_assignment(self.backend, self.usbdev_ident, auto_attach=True)
422421
assign(self, self.frontend.devices['usb'], ass)
423422
self.assertIsNone(usb_dev.attachment)
424423
try:
@@ -432,10 +431,14 @@ def test_010_assign(self):
432431

433432
self.assertEqual(usb_dev.attachment, self.frontend)
434433

434+
@unittest.mock.patch('qubes.ext.utils.confirm_device_attachment')
435435
@unittest.skipIf(LEGACY, "new feature")
436-
def test_011_assign_ask(self):
436+
def test_011_assign_ask(self, confirm):
437+
confirm.return_value = self.frontend.name
437438
usb_dev = self.backend.devices['usb'][self.usbdev_ident]
438-
ass = make_assignment(self.backend, self.usbdev_ident, required=True)
439+
ass = DeviceAssignment(VirtualDevice(Port(
440+
self.backend, self.usbdev_ident, 'usb')),
441+
mode='ask-to-attach')
439442
assign(self, self.frontend.devices['usb'], ass)
440443
self.assertIsNone(usb_dev.attachment)
441444
try:
@@ -488,7 +491,7 @@ def test_030_detach(self):
488491

489492
def test_040_unassign(self):
490493
usb_dev = self.backend.devices['usb'][self.usbdev_ident]
491-
ass = make_assignment(self.backend, self.usbdev_ident, required=True)
494+
ass = make_assignment(self.backend, self.usbdev_ident, auto_attach=True)
492495
assign(self, self.frontend.devices['usb'], ass)
493496
self.assertIsNone(usb_dev.attachment)
494497
unassign(self, self.frontend.devices['usb'], ass)
@@ -540,7 +543,7 @@ def test_060_auto_detach_on_remove(self):
540543
def test_061_auto_attach_on_reconnect(self):
541544
self.frontend.start()
542545
usb_list = self.backend.devices['usb']
543-
ass = make_assignment(self.backend, self.usbdev_ident, required=True)
546+
ass = make_assignment(self.backend, self.usbdev_ident, auto_attach=True)
544547
try:
545548
assign(self, self.frontend.devices['usb'], ass)
546549
except qubesusbproxy.core3ext.USBProxyNotInstalled as e:
@@ -568,7 +571,7 @@ def test_061_auto_attach_on_reconnect(self):
568571
def test_062_ask_to_attach_on_start(self):
569572
self.frontend.start()
570573
usb_list = self.backend.devices['usb']
571-
ass = make_assignment(self.backend, self.usbdev_ident, required=True)
574+
ass = make_assignment(self.backend, self.usbdev_ident, auto_attach=True)
572575
try:
573576
assign(self, self.frontend.devices['usb'], ass)
574577
except qubesusbproxy.core3ext.USBProxyNotInstalled as e:
@@ -855,8 +858,10 @@ def test_012_on_qdb_change_multiple_assignments_dev(self):
855858
self.assertEqual(self.ext.attach_and_notify.call_args[0][1].options,
856859
{'any': 'did'})
857860

858-
@unittest.mock.patch('subprocess.Popen')
859-
def test_013_on_qdb_change_two_fronts_failed(self, mock_confirm):
861+
# replace async function with sync one
862+
@unittest.mock.patch('qubes.ext.utils.confirm_device_attachment',
863+
new_callable=Mock)
864+
def test_013_on_qdb_change_two_fronts_failed(self, _confirm):
860865
back, front = self.added_assign_setup()
861866

862867
exp_dev = qubesusbproxy.core3ext.USBDevice(back, '1-1')
@@ -866,18 +871,22 @@ def test_013_on_qdb_change_two_fronts_failed(self, mock_confirm):
866871
back.devices['usb']._assigned.append(assign)
867872
back.devices['usb']._exposed.append(exp_dev)
868873

869-
proc = Mock()
870-
proc.communicate = Mock()
871-
proc.communicate.return_value = (b'nonsense', b'')
872-
mock_confirm.return_value = proc
874+
class quick_mock:
875+
@staticmethod
876+
def result():
877+
return "nonsense"
878+
873879
self.ext.attach_and_notify = Mock()
874-
with mock.patch('asyncio.ensure_future'):
880+
with mock.patch('asyncio.ensure_future') as future:
881+
future.return_value = quick_mock
875882
self.ext.on_qdb_change(back, None, None)
876-
proc.communicate.assert_called_once()
883+
877884
self.ext.attach_and_notify.assert_not_called()
878885

879-
@unittest.mock.patch('subprocess.Popen')
880-
def test_014_on_qdb_change_two_fronts(self, mock_confirm):
886+
# replace async function with sync one
887+
@unittest.mock.patch('qubes.ext.utils.confirm_device_attachment',
888+
new_callable=Mock)
889+
def test_014_on_qdb_change_two_fronts(self, _confirm):
881890
back, front = self.added_assign_setup()
882891

883892
exp_dev = qubesusbproxy.core3ext.USBDevice(back, '1-1')
@@ -887,16 +896,17 @@ def test_014_on_qdb_change_two_fronts(self, mock_confirm):
887896
back.devices['usb']._assigned.append(assign)
888897
back.devices['usb']._exposed.append(exp_dev)
889898

890-
proc = Mock()
891-
proc.communicate = Mock()
892-
proc.communicate.return_value = (b'front-vm', b'')
893-
mock_confirm.return_value = proc
899+
class quick_mock:
900+
@staticmethod
901+
def result():
902+
return "front-vm"
903+
894904
self.ext.attach_and_notify = Mock()
895-
with mock.patch('asyncio.ensure_future'):
905+
with mock.patch('asyncio.ensure_future') as future:
906+
future.return_value = quick_mock
896907
self.ext.on_qdb_change(back, None, None)
897-
proc.communicate.assert_called_once()
898-
self.ext.attach_and_notify.assert_called_once_with(
899-
front, assign)
908+
909+
self.ext.attach_and_notify.assert_called_once_with(front, assign)
900910
# don't ask again
901911
self.assertEqual(self.ext.attach_and_notify.call_args[0][1].mode.value,
902912
'auto-attach')
@@ -915,6 +925,7 @@ def test_015_on_qdb_change_ask(self):
915925
self.ext.on_qdb_change(back, None, None)
916926
self.assertEqual(self.ext.attach_and_notify.call_args[0][1].mode.value,
917927
'ask-to-attach')
928+
918929
def test_020_on_startup_multiple_assignments_including_full(self):
919930
back, front = self.added_assign_setup()
920931

@@ -936,10 +947,9 @@ def test_020_on_startup_multiple_assignments_including_full(self):
936947
back.devices['usb']._exposed.append(
937948
qubesusbproxy.core3ext.USBDevice(back, '1-1'))
938949

939-
self.ext.attach_and_notify = Mock()
950+
self.ext.attach_and_notify = AsyncMock()
940951
loop = asyncio.get_event_loop()
941-
with mock.patch('asyncio.ensure_future'):
942-
loop.run_until_complete(self.ext.on_domain_start(front, None))
952+
loop.run_until_complete(self.ext.on_domain_start(front, None))
943953
self.assertEqual(self.ext.attach_and_notify.call_args[0][1].options,
944954
{'pid': 'did'})
945955

@@ -961,9 +971,8 @@ def test_021_on_startup_multiple_assignments_port_vs_dev(self):
961971
qubesusbproxy.core3ext.USBDevice(back, '1-1'))
962972

963973
loop = asyncio.get_event_loop()
964-
self.ext.attach_and_notify = Mock()
965-
with mock.patch('asyncio.ensure_future'):
966-
loop.run_until_complete(self.ext.on_domain_start(front, None))
974+
self.ext.attach_and_notify = AsyncMock()
975+
loop.run_until_complete(self.ext.on_domain_start(front, None))
967976
self.assertEqual(self.ext.attach_and_notify.call_args[0][1].options,
968977
{'pid': 'any'})
969978

@@ -986,10 +995,9 @@ def test_022_on_startup_multiple_assignments_dev(self):
986995
back.devices['usb']._exposed.append(
987996
qubesusbproxy.core3ext.USBDevice(back, '1-2'))
988997

989-
self.ext.attach_and_notify = Mock()
998+
self.ext.attach_and_notify = AsyncMock()
990999
loop = asyncio.get_event_loop()
991-
with mock.patch('asyncio.ensure_future'):
992-
loop.run_until_complete(self.ext.on_domain_start(front, None))
1000+
loop.run_until_complete(self.ext.on_domain_start(front, None))
9931001
self.assertEqual(self.ext.attach_and_notify.call_args[0][1].options,
9941002
{'any': 'did'})
9951003

@@ -1001,7 +1009,7 @@ def test_023_on_startup_already_attached(self):
10011009
exp_dev.port, exp_dev.device_id), mode='auto-attach')
10021010

10031011
front.devices['usb']._assigned.append(assign)
1004-
attached_device = back.devices['usb']._exposed.append(exp_dev)
1012+
back.devices['usb']._exposed.append(exp_dev)
10051013

10061014
self.ext.attach_and_notify = Mock()
10071015
loop = asyncio.get_event_loop()

qubesusbproxy/utils.py

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2020
# USA.
2121
import asyncio
22-
import subprocess
2322
import sys
2423

2524
import qubes

0 commit comments

Comments
 (0)