Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/pr/647'
Browse files Browse the repository at this point in the history
* origin/pr/647:
  tests: add qrexec performance tests

Pull request description:

Add simple connection latency, and throughput tests. Run them with
different type of services (scripts, socket, via fork-server or not).
They print a test run time for comparison - the lower the better.

QubesOS/qubes-issues#5740

This will be especially useful to measure impact of QubesOS/qubes-core-qrexec#141 and similar changes.
  • Loading branch information
marmarek committed Jan 26, 2025
2 parents a784c37 + 6c06362 commit 1f2dbf5
Show file tree
Hide file tree
Showing 5 changed files with 376 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ endif
mkdir -p "$(DESTDIR)$(FILESDIR)"
cp -r templates "$(DESTDIR)$(FILESDIR)/templates"
cp -r tests-data "$(DESTDIR)$(FILESDIR)/tests-data"
mkdir -p "$(DESTDIR)/usr/lib/qubes"
cp -r tests "$(DESTDIR)/usr/lib/qubes/"
rm -f "$(DESTDIR)$(FILESDIR)/templates/README"

mkdir -p "$(DESTDIR)$(DOCDIR)"
Expand Down
1 change: 1 addition & 0 deletions qubes/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1825,6 +1825,7 @@ def load_tests(loader, tests, pattern): # pylint: disable=unused-argument
"qubes.tests.integ.devices_block",
"qubes.tests.integ.devices_pci",
"qubes.tests.integ.qrexec",
"qubes.tests.integ.qrexec_perf",
"qubes.tests.integ.dom0_update",
"qubes.tests.integ.vm_update",
"qubes.tests.integ.network",
Expand Down
117 changes: 117 additions & 0 deletions qubes/tests/integ/qrexec_perf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#
# The Qubes OS Project, https://www.qubes-os.org/
#
# Copyright (C) 2025 Marek Marczykowski-Górecki
# <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

import asyncio
import os
import subprocess
import sys
import time

import qubes.tests


class TC_00_QrexecPerfMixin:
def setUp(self: qubes.tests.SystemTestCase):
super().setUp()
self.vm1 = self.app.add_new_vm(
"AppVM",
name=self.make_vm_name("vm1"),
label="red",
)
self.vm2 = self.app.add_new_vm(
"AppVM",
name=self.make_vm_name("vm2"),
label="red",
)
self.loop.run_until_complete(
asyncio.gather(
self.vm1.create_on_disk(),
self.vm2.create_on_disk(),
)
)
self.loop.run_until_complete(
asyncio.gather(
self.vm1.start(),
self.vm2.start(),
)
)

def run_test(self, name):
cmd = [
"/usr/lib/qubes/tests/qrexec_perf.py",
f"--vm1={self.vm1.name}",
f"--vm2={self.vm2.name}",
name,
]
p = self.loop.run_until_complete(asyncio.create_subprocess_exec(*cmd))
self.loop.run_until_complete(p.wait())
if p.returncode:
self.fail(f"'{' '.join(cmd)}' failed: {p.returncode}")

def test_000_simple(self):
"""Measure simple exec-based vm-vm calls latency"""
self.loop.run_until_complete(self.wait_for_session(self.vm2))
self.run_test("exec")

def test_010_simple_root(self):
"""Measure simple exec-based vm-vm calls latency, use root to
bypass qrexec-fork-server"""
self.run_test("exec-root")

def test_020_socket(self):
"""Measure simple socket-based vm-vm calls latency"""
self.run_test("socket")

def test_030_socket_root(self):
"""Measure simple socket-based vm-vm calls latency, use root to
bypass qrexec-fork-server"""
self.run_test("socket-root")

def test_100_simple_data_simplex(self):
"""Measure simple exec-based vm-vm calls throughput"""
self.run_test("exec-data-simplex")

def test_110_simple_data_duplex(self):
"""Measure simple exec-based vm-vm calls throughput"""
self.run_test("exec-data-duplex")

def test_120_simple_data_duplex_root(self):
"""Measure simple exec-based vm-vm calls throughput"""
self.run_test("exec-data-duplex-root")

def test_130_socket_data_duplex(self):
"""Measure simple socket-based vm-vm calls throughput"""
self.run_test("socket-data-duplex")


def create_testcases_for_templates():
return qubes.tests.create_testcases_for_templates(
"TC_00_QrexecPerf",
TC_00_QrexecPerfMixin,
qubes.tests.SystemTestCase,
module=sys.modules[__name__],
)


def load_tests(loader, tests, pattern):
tests.addTests(loader.loadTestsFromNames(create_testcases_for_templates()))
return tests


qubes.tests.maybe_create_testcases_on_import(create_testcases_for_templates)
2 changes: 2 additions & 0 deletions rpm_spec/core-dom0.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ done
%{python3_sitelib}/qubes/tests/integ/grub.py
%{python3_sitelib}/qubes/tests/integ/salt.py
%{python3_sitelib}/qubes/tests/integ/qrexec.py
%{python3_sitelib}/qubes/tests/integ/qrexec_perf.py
%{python3_sitelib}/qubes/tests/integ/storage.py
%{python3_sitelib}/qubes/tests/integ/vm_qrexec_gui.py

Expand All @@ -547,6 +548,7 @@ done
/usr/lib/qubes/cleanup-dispvms
/usr/lib/qubes/fix-dir-perms.sh
/usr/lib/qubes/startup-misc.sh
/usr/lib/qubes/tests/qrexec_perf.py
%{_unitdir}/[email protected]/30_qubes.conf
%{_unitdir}/qubes-core.service
%{_unitdir}/qubes-qmemman.service
Expand Down
Loading

0 comments on commit 1f2dbf5

Please sign in to comment.