From e2529c79abef871a68b5feb3906f7afa0eecf0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 30 Nov 2024 14:12:45 +0100 Subject: [PATCH 01/15] tests: add skipIfTemplate decorator This allows more effective skipping tests for specific templates - without doing any setUp/tearDown. --- qubes/tests/__init__.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/qubes/tests/__init__.py b/qubes/tests/__init__.py index 4189ed06c..c9f4f4969 100644 --- a/qubes/tests/__init__.py +++ b/qubes/tests/__init__.py @@ -154,6 +154,22 @@ def skipUnlessEnv(varname): return unittest.skipUnless(os.getenv(varname), "no {} set".format(varname)) +def skipIfTemplate(*templates): + """Decorator generator for skipping on specific templates. + + Some tests are supported only on some templates. This decorator allows + excluding test for some of them, especially useful for excluding tests on + minimal templates or Whonix. + Multiple templates can be given. + """ + + def decorator(func): + func.__qubestest_skip_templates__ = templates + return func + + return decorator + + class TestEmitter(qubes.events.Emitter): """Dummy event emitter which records events fired on it. @@ -439,9 +455,17 @@ class QubesTestCase(unittest.TestCase): def __init__(self, methodName="runTest"): try: test_method = getattr(self, methodName) - setattr( - self, methodName, _clear_ex_info(self.set_result)(test_method) - ) + skip_templates = getattr( + self, "__qubestest_skip_templates__", [] + ) or getattr(test_method, "__qubestest_skip_templates__", []) + template = getattr(self, "template", "") + if any(skip in template for skip in skip_templates): + test_method = unittest.skip( + f"Test skipped on template {template}" + )(test_method) + else: + test_method = _clear_ex_info(self.set_result)(test_method) + setattr(self, methodName, test_method) except AttributeError: pass super(QubesTestCase, self).__init__(methodName) From 52d60e6a9e3094dfd5285654e18046dd57cff616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 30 Nov 2024 14:15:23 +0100 Subject: [PATCH 02/15] tests: use new decorator to skip network tests on whonix --- qubes/tests/integ/network.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qubes/tests/integ/network.py b/qubes/tests/integ/network.py index 76eae9674..6657c198e 100644 --- a/qubes/tests/integ/network.py +++ b/qubes/tests/integ/network.py @@ -34,6 +34,7 @@ # noinspection PyAttributeOutsideInit,PyPep8Naming +@qubes.tests.skipIfTemplate("whonix") class VmNetworkingMixin(object): test_ip = "192.168.123.45" test_name = "test.example.com" From 3f4f65ecf3e9657b27aa5ba876d3070f1bc62bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 30 Nov 2024 14:25:08 +0100 Subject: [PATCH 03/15] tests: allow testing minimal template as salt target... ... using another template for management dvm. That other template can be selected with QUBES_TEST_MGMT_TPL variable. For this to fully work, test updating a template instead of AppVM, as it will use updates proxy which should work with minimal template (contrary to direct network access). --- qubes/tests/integ/salt.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/qubes/tests/integ/salt.py b/qubes/tests/integ/salt.py index 19bfde313..3c33ae6d9 100644 --- a/qubes/tests/integ/salt.py +++ b/qubes/tests/integ/salt.py @@ -311,12 +311,28 @@ def setUp(self): super(SaltVMTestMixin, self).setUp() self.init_default_template(self.template) + mgmt_tpl = self.app.domains[self.template] + if "minimal" in self.template: + # minimal template doesn't support being mgmt vm, but still test + # it being a target + mgmt_tpl = os.environ.get("QUBES_TEST_MGMT_TPL") + if not mgmt_tpl: + mgmt_tpl = str(self.host_app.default_template) + print( + f"Using {mgmt_tpl} template for mgmt vm when testing " + f"minimal template as target. You can set " + f"QUBES_TEST_MGMT_TPL env variable to use " + f"different template for mgmt vm" + ) + mgmt_tpl = self.app.domains[mgmt_tpl] + dispvm_tpl_name = self.make_vm_name("disp-tpl") dispvm_tpl = self.app.add_new_vm( "AppVM", label="red", template_for_dispvms=True, name=dispvm_tpl_name, + template=mgmt_tpl, ) self.loop.run_until_complete(dispvm_tpl.create_on_disk()) self.app.default_dispvm = dispvm_tpl @@ -611,8 +627,10 @@ def test_002_grains_id(self): def test_003_update(self): vmname = self.make_vm_name("target") - self.vm = self.app.add_new_vm("AppVM", name=vmname, label="red") - self.loop.run_until_complete(self.vm.create_on_disk()) + self.vm = self.app.add_new_vm("TemplateVM", name=vmname, label="red") + self.loop.run_until_complete( + self.vm.clone_disk_files(self.app.default_template) + ) # start the VM manually, so it stays running after applying salt state self.loop.run_until_complete(self.vm.start()) state_output = self.salt_call( From 1266acba6d1ef83b72ff83bd9575aa9732d38dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 30 Nov 2024 15:02:34 +0100 Subject: [PATCH 04/15] tests: test ptyxis on newer fedora template instead of gnome-terminal QubesOS/qubes-issues#9244 --- qubes/tests/integ/vm_qrexec_gui.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qubes/tests/integ/vm_qrexec_gui.py b/qubes/tests/integ/vm_qrexec_gui.py index 1f9c0e02f..021c688e5 100644 --- a/qubes/tests/integ/vm_qrexec_gui.py +++ b/qubes/tests/integ/vm_qrexec_gui.py @@ -123,7 +123,9 @@ def test_011_run_gnome_terminal(self): self.loop.run_until_complete(self.testvm1.start()) self.assertEqual(self.testvm1.get_power_state(), "Running") self.loop.run_until_complete(self.wait_for_session(self.testvm1)) - p = self.loop.run_until_complete(self.testvm1.run("gnome-terminal")) + p = self.loop.run_until_complete( + self.testvm1.run("gnome-terminal || " "ptyxis") + ) try: title = "user@{}".format(self.testvm1.name) if self.template.count("whonix"): @@ -156,7 +158,7 @@ def test_011_run_gnome_terminal(self): wait_count += 1 if wait_count > 100: self.fail( - "Timeout while waiting for gnome-terminal " + "Timeout while waiting for gnome-terminal/ptyxis " "termination" ) self.loop.run_until_complete(asyncio.sleep(0.1)) From 163a6cdf47c499280d33f740998fe0ebd0530f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 30 Nov 2024 15:10:50 +0100 Subject: [PATCH 05/15] tests: support not installing extra packages for in-vm kernel tests This makes sense for testing if in-vm kernel works out of the box in selected templates. QubesOS/qubes-issues#5212 --- qubes/tests/integ/grub.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qubes/tests/integ/grub.py b/qubes/tests/integ/grub.py index 9acde4060..bcbea77af 100644 --- a/qubes/tests/integ/grub.py +++ b/qubes/tests/integ/grub.py @@ -46,6 +46,13 @@ def setUp(self): ) def install_packages(self, vm): + if os.environ.get("QUBES_TEST_SKIP_KERNEL_INSTALL") == "1": + return + else: + print( + "Installing kernel packages, you can skip by setting " + "QUBES_TEST_SKIP_KERNEL_INSTALL=1 in environment" + ) if self.template.startswith("fedora-"): cmd_install1 = ( "dnf clean expire-cache && " From 469e14779c45139da0b9b2503d5171a3a7aa26fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 30 Nov 2024 15:44:31 +0100 Subject: [PATCH 06/15] tests: do not skip network tests on minimal template Plain minimial template wont work, but this allows testing if minimal + just networking packages installed. Specifically, this tests if installing qubes-core-agent-networking is enough to get networking working with minimal template. --- qubes/tests/integ/network.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/qubes/tests/integ/network.py b/qubes/tests/integ/network.py index 6657c198e..b7e22b4f9 100644 --- a/qubes/tests/integ/network.py +++ b/qubes/tests/integ/network.py @@ -72,11 +72,6 @@ def setUp(self): "Test not supported here - Whonix uses its own " "firewall settings" ) - if self.template.endswith("-minimal"): - self.skipTest( - "Test not supported here - minimal template don't have " - "networking packages by default" - ) self.init_default_template(self.template) self.testnetvm = self.app.add_new_vm( qubes.vm.appvm.AppVM, name=self.make_vm_name("netvm1"), label="red" From bd7b71b854acf3dd5eaad207fa922834c82d4df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Mon, 2 Dec 2024 04:37:17 +0100 Subject: [PATCH 07/15] tests: adjust update tests for minimal template Skip only the direct (no-proxy) update test, as minimal template doesn't have networking packages included. But do test all scenarios with proxy, just use the default template for repo-hosting VM. --- qubes/tests/integ/vm_update.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/qubes/tests/integ/vm_update.py b/qubes/tests/integ/vm_update.py index 819c45fed..53d1fc6e1 100644 --- a/qubes/tests/integ/vm_update.py +++ b/qubes/tests/integ/vm_update.py @@ -244,6 +244,15 @@ def setUp(self): self.loop.run_until_complete(self.testvm1.create_on_disk()) self.repo_proc = None + # template used for repo-hosting vm + self.repo_template = self.app.default_template + if self.template.count("minimal"): + self.repo_template = self.host_app.default_template + print( + f"Using {self.repo_template!s} for repo hosting vm when " + f"testing minimal template" + ) + def tearDown(self): if self.repo_proc: self.repo_proc.terminate() @@ -256,6 +265,10 @@ def test_000_simple_update(self): :type self: qubes.tests.SystemTestCase | VmUpdatesMixin """ + if self.template.count("minimal"): + self.skipTest( + "Template {} not supported by this test".format(self.template) + ) self.app.save() self.testvm1 = self.app.domains[self.testvm1.qid] self.loop.run_until_complete(self.testvm1.start()) @@ -449,7 +462,10 @@ def start_vm_with_proxy_repo(self): :type self: qubes.tests.SystemTestCase | VmUpdatesMixin """ self.netvm_repo = self.app.add_new_vm( - qubes.vm.appvm.AppVM, name=self.make_vm_name("net"), label="red" + qubes.vm.appvm.AppVM, + name=self.make_vm_name("net"), + label="red", + template=self.repo_template, ) self.netvm_repo.provides_network = True self.loop.run_until_complete(self.netvm_repo.create_on_disk()) @@ -574,11 +590,6 @@ def update_via_proxy_qubes_vm_update_impl( :type break_repo: bool :type: expect_updated: bool """ - if self.template.count("minimal"): - self.skipTest( - "Template {} not supported by this test".format(self.template) - ) - if expected_ret_codes is None: expected_ret_codes = self.ret_code_ok From bff48125333fbd241cbfc4ee7da2c657673a4c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Tue, 3 Dec 2024 03:23:23 +0100 Subject: [PATCH 08/15] tests: give more RAM for HVM with in-vm kernel HVM has disabled memory hotplug (due to incompatibility with QEMU), and so needs more RAM to fit everything + memory accounting for full maxmem. While at it, adjust the test to check if kernel-related settings are correctly inherited from the template. --- qubes/tests/integ/grub.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/qubes/tests/integ/grub.py b/qubes/tests/integ/grub.py index bcbea77af..d0f3e3012 100644 --- a/qubes/tests/integ/grub.py +++ b/qubes/tests/integ/grub.py @@ -129,6 +129,11 @@ def test_000_standalone_vm(self): self.loop.run_until_complete(self.testvm1.shutdown(wait=True)) self.testvm1.kernel = self.kernel + if self.virt_mode == "hvm": + # HVM has disabled memory-hotplug, which means VM is started with + # full maxmem and need extra memory for page structures for full + # maxmem + self.testvm1.memory = 450 self.loop.run_until_complete(self.testvm1.start()) (actual_kver, _) = self.loop.run_until_complete( self.testvm1.run_for_stdio("uname -r") @@ -156,7 +161,6 @@ def test_010_template_based_vm(self): name=self.make_vm_name("vm1"), label="red", ) - self.testvm1.virt_mode = self.virt_mode self.loop.run_until_complete(self.testvm1.create_on_disk()) self.loop.run_until_complete(self.test_template.start()) self.install_packages(self.test_template) @@ -164,7 +168,11 @@ def test_010_template_based_vm(self): self.loop.run_until_complete(self.test_template.shutdown(wait=True)) self.test_template.kernel = self.kernel - self.testvm1.kernel = self.kernel + if self.virt_mode == "hvm": + # HVM has disabled memory-hotplug, which means VM is started with + # full maxmem and need extra memory for page structures for full + # maxmem + self.test_template.memory = 450 # Check if TemplateBasedVM boots and has the right kernel self.loop.run_until_complete(self.testvm1.start()) From 817e9fe7fdee8df78d5440b1cb95d56db0d81e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 6 Dec 2024 15:33:26 +0100 Subject: [PATCH 09/15] tests: do not wait on skipped tests When QUBES_TEST_WAIT_ON_FAIL=1 is set, do not wait if the test raises SkipTest exception. It's an expected behavior, not a real failure. --- qubes/tests/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qubes/tests/__init__.py b/qubes/tests/__init__.py index c9f4f4969..1fd5894df 100644 --- a/qubes/tests/__init__.py +++ b/qubes/tests/__init__.py @@ -269,6 +269,8 @@ def wait_on_fail(func): def wrapper(self, *args, **kwargs): try: func(self, *args, **kwargs) + except unittest.case.SkipTest: + raise except: print("FAIL\n") traceback.print_exc() From 9982ab39962c295caea596bb284c5d0ad152a3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 7 Dec 2024 17:35:13 +0100 Subject: [PATCH 10/15] tests: log stderr from upgrades-status-notify --- qubes/tests/integ/vm_update.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubes/tests/integ/vm_update.py b/qubes/tests/integ/vm_update.py index 53d1fc6e1..52dce3e6a 100644 --- a/qubes/tests/integ/vm_update.py +++ b/qubes/tests/integ/vm_update.py @@ -654,7 +654,7 @@ def upgrade_status_notify(self): """ self.loop.run_until_complete( self.testvm1.run_for_stdio( - "/usr/lib/qubes/upgrades-status-notify", + "/usr/lib/qubes/upgrades-status-notify 2>/dev/console", user="root", ) ) From e41995a1725c3c1948dec6a37a0bba42cc028507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 7 Dec 2024 23:07:53 +0100 Subject: [PATCH 11/15] tests: retry pactl move-source-output if necessary It seems pactl still exits with code 0 even if the change wasn't made. There is no info about it on stderr either. Verify if source-output was changed after the call, and if not - retry. --- qubes/tests/integ/audio.py | 92 +++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/qubes/tests/integ/audio.py b/qubes/tests/integ/audio.py index 52311f41b..0a1c74d56 100644 --- a/qubes/tests/integ/audio.py +++ b/qubes/tests/integ/audio.py @@ -253,47 +253,52 @@ def common_audio_playback(self): p.wait() self.check_audio_sample(recorded_audio.file.read(), sfreq) - def _configure_audio_recording(self, vm): - """Connect VM's source-output to sink monitor instead of mic""" + def _call_in_audiovm(self, audiovm, command): local_user = grp.getgrnam("qubes").gr_mem[0] - audiovm = vm.audiovm - sudo = ["sudo", "-E", "-u", local_user] - - source_outputs_cmd = ["pactl", "-f", "json", "list", "source-outputs"] if audiovm.name != "dom0": stdout, _ = self.loop.run_until_complete( - audiovm.run_for_stdio(" ".join(source_outputs_cmd)) + audiovm.run_for_stdio(" ".join(command)) ) - source_outputs = json.loads(stdout) + return stdout else: - source_outputs = json.loads( - subprocess.check_output(sudo + source_outputs_cmd) - ) - - if not source_outputs: - self.fail("no source-output found in {}".format(audiovm.name)) - assert False + return subprocess.check_output(sudo + command) + def _find_pactl_entry_for_vm(self, pactl_data, vm_name): try: - output_index = [ - s["index"] - for s in source_outputs - if s["properties"].get("application.name") == vm.name + return [ + s + for s in pactl_data + if s["properties"].get("application.name") == vm_name ][0] except IndexError: self.fail("source-output for VM {} not found".format(vm.name)) # self.fail never returns assert False - sources_cmd = ["pactl", "-f", "json", "list", "sources"] - if audiovm.name != "dom0": - res, _ = self.loop.run_until_complete( - audiovm.run_for_stdio(" ".join(sources_cmd)) + def _configure_audio_recording(self, vm): + """Connect VM's source-output to sink monitor instead of mic""" + audiovm = vm.audiovm + + source_outputs = json.loads( + self._call_in_audiovm( + audiovm, ["pactl", "-f", "json", "list", "source-outputs"] ) - sources = json.loads(res) - else: - sources = json.loads(subprocess.check_output(sudo + sources_cmd)) + ) + + if not source_outputs: + self.fail("no source-output found in {}".format(audiovm.name)) + assert False + + output_info = self._find_pactl_entry_for_vm(source_outputs, vm.name) + output_index = output_info["index"] + current_source = output_info["source"] + + sources = json.loads( + self._call_in_audiovm( + audiovm, ["pactl", "-f", "json", "list", "sources"] + ) + ) if not sources: self.fail("no sources found in {}".format(audiovm.name)) @@ -308,16 +313,31 @@ def _configure_audio_recording(self, vm): # self.fail never returns assert False - cmd = [ - "pactl", - "move-source-output", - str(output_index), - str(source_index), - ] - if audiovm.name != "dom0": - self.loop.run_until_complete(audiovm.run(" ".join(cmd))) - else: - subprocess.check_call(sudo + cmd) + attempts_left = 5 + # pactl seems to fail sometimes, still with exit code 0... + while current_source != source_index and attempts_left: + assert isinstance(output_index, int) + assert isinstance(source_index, int) + cmd = [ + "pactl", + "move-source-output", + str(output_index), + str(source_index), + ] + self._call_in_audiovm(audiovm, cmd) + + source_outputs = json.loads( + self._call_in_audiovm( + audiovm, ["pactl", "-f", "json", "list", "source-outputs"] + ) + ) + + output_info = self._find_pactl_entry_for_vm(source_outputs, vm.name) + output_index = output_info["index"] + current_source = output_info["source"] + attempts_left -= 1 + + self.assertGreater(attempts_left, 0, "Failed to move-source-output") async def retrieve_audio_input(self, vm, status): try: From 2295b7a2be52ed5da52b703b4094915de6117ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sun, 8 Dec 2024 05:21:52 +0100 Subject: [PATCH 12/15] tests: use new decorator to skip audio tests on whonix-gateway It's faster as the test is skipped before calling setUp(). --- qubes/tests/integ/audio.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qubes/tests/integ/audio.py b/qubes/tests/integ/audio.py index 0a1c74d56..4c1fcbf39 100644 --- a/qubes/tests/integ/audio.py +++ b/qubes/tests/integ/audio.py @@ -34,6 +34,7 @@ from qubes.tests.integ.vm_qrexec_gui import TC_00_AppVMMixin, in_qemu +@qubes.tests.skipIfTemplate("whonix-g") class TC_00_AudioMixin(TC_00_AppVMMixin): def wait_for_pulseaudio_startup(self, vm): self.loop.run_until_complete(self.wait_for_session(self.testvm1)) @@ -64,8 +65,6 @@ def wait_for_pulseaudio_startup(self, vm): self.loop.run_until_complete(asyncio.sleep(1)) def prepare_audio_test(self, backend): - if "whonix-g" in self.template: - self.skipTest("whonix gateway have no audio") self.loop.run_until_complete(self.testvm1.start()) pulseaudio_units = "pulseaudio.socket pulseaudio.service" pipewire_units = "pipewire.socket wireplumber.service pipewire.service" From 430b63363e0cd16fe343565b4a913008764ed5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sun, 8 Dec 2024 16:06:24 +0100 Subject: [PATCH 13/15] storage/lvm: don't crash on calculating metadata size for not active LV Those do not have usage info available, so return None for metadata usage, instead of crashing on `float('')` call. Fixes: 6dffbf93 "storage/lvm: allow starting a VM even if not all its volumes are active" --- qubes/storage/lvm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index 1012bb3fb..dcd9e8a54 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -266,7 +266,7 @@ def _parse_lvm_cache(lvm_output): usage = int(size / 100 * float(usage_percent)) else: usage = 0 - if metadata_size: + if metadata_size and metadata_percent: metadata_size = int(metadata_size[:-1]) metadata_usage = int(metadata_size / 100 * float(metadata_percent)) else: From 6b49ea670bcf2bd61954c01d001f812578dc5c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Mon, 9 Dec 2024 01:33:12 +0100 Subject: [PATCH 14/15] tests: fix race condition in updates test Wait for the local repo to become available - python3 -m http may take a moment, and if the other parts are quick, the test would fail on connection refused error. --- qubes/tests/integ/vm_update.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qubes/tests/integ/vm_update.py b/qubes/tests/integ/vm_update.py index 52dce3e6a..3d661b2db 100644 --- a/qubes/tests/integ/vm_update.py +++ b/qubes/tests/integ/vm_update.py @@ -409,6 +409,13 @@ def create_repo_and_serve(self): "Template {} not supported by this test".format(self.template) ) + # wait for the repo to become reachable + self.loop.run_until_complete( + self.netvm_repo.run_for_stdio( + "while ! curl http://localhost:8080/ >/dev/null; do sleep 0.5; done" + ) + ) + def add_update_to_repo(self): """ :type self: qubes.tests.SystemTestCase | VmUpdatesMixin From 452b6a3bc071627c42b33219402685a403c05c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Mon, 9 Dec 2024 01:35:11 +0100 Subject: [PATCH 15/15] tests: increase timeout in clipboard test The point of the test is not its speed, but whether it eventually happens. On the other hand, some of the test runners can be quite slow under load. --- qubes/tests/integ/basic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubes/tests/integ/basic.py b/qubes/tests/integ/basic.py index 19deccbf1..54be7b0b3 100644 --- a/qubes/tests/integ/basic.py +++ b/qubes/tests/integ/basic.py @@ -636,7 +636,7 @@ async def _test_clipboard( # correct timestamp (so gui-daemon would not drop the copy request) subprocess.check_call(["xdotool", "key", "ctrl+a", "ctrl+c"]) # wait a bit to let the zenity actually copy - await asyncio.sleep(1) + await asyncio.sleep(5) subprocess.check_call(["xdotool", "key", "ctrl+shift+c", "Escape"]) await self.wait_for_window_coro(window_title, show=False)