Skip to content

Commit 8ec93a6

Browse files
committed
ci: add and integrate qemu_guest_test.py
This allows us to write tests that run natively on the guest, and qemu_test.py will invoke them using qemu. Signed-off-by: Robie Basak <robie.basak@oss.qualcomm.com>
1 parent ba629bb commit 8ec93a6

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

ci/qemu_guest_test.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""qemu-based tests that are copied into the guest and run there"""
2+
3+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
6+
# These tests are run inside the qemu guest as root using its own pytest runner
7+
# invocation.
8+
9+
import pytest
10+
11+
# Mark this module so that the main test runner can skip it when running from
12+
# the host. However, the guest test runner does not use this mark but instead
13+
# explicitly calls this file. Marks require test collection, and the guest test
14+
# runner isn't going to have dependencies installed that are only needed for
15+
# host tests, causing guest test collection to fail otherwise.
16+
pytestmark = pytest.mark.guest
17+
18+
19+
def test_empty():
20+
# The empty test. This is nevertheless useful as its presence ensures that
21+
# the host is calling the guest test suite in this module correctly.
22+
pass

ci/qemu_test.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
import pexpect
1414
import pytest
1515

16+
# Since the first test checks for the mandatory password reset functionality
17+
# that also prepares the VM for shell-based access, we make the additional
18+
# optimisation that the fixture for a logged in VM re-uses that VM, so the
19+
# ordering of [plain VM fixture, password reset test, logged-in VM fixture]
20+
# matters here.
21+
1622

1723
@pytest.fixture(scope="module")
1824
def vm():
@@ -58,10 +64,14 @@ def vm():
5864
"-nographic",
5965
"-bios",
6066
"/usr/share/AAVMF/AAVMF_CODE.fd",
67+
"-fsdev",
68+
f"local,id=fsdev0,path={os.getcwd()},security_model=none",
69+
"-device",
70+
"virtio-9p-pci,fsdev=fsdev0,mount_tag=qcom-deb-images",
6171
],
6272
)
6373
spawn.logfile = sys.stdout.buffer
64-
yield types.SimpleNamespace(spawn=spawn)
74+
yield types.SimpleNamespace(spawn=spawn, logged_in=False)
6575

6676
# No need to be nice; that would take time
6777
spawn.kill(signal.SIGKILL)
@@ -89,3 +99,42 @@ def test_password_reset_required(vm):
8999
vm.spawn.expect_exact("Retype new password:")
90100
vm.spawn.send("new password\r\n")
91101
vm.spawn.expect_exact("debian@debian:~$")
102+
103+
vm.logged_in = True
104+
105+
106+
@pytest.fixture(scope="module")
107+
def logged_in_vm(vm):
108+
if not vm.logged_in:
109+
pytest.skip("Password reset test did not run or failed")
110+
return vm
111+
112+
113+
def test_using_guest_tests(logged_in_vm):
114+
"""Run the tests in qemu_guest_test.py inside the qemu guest"""
115+
# Statement of test success and failure that are unlikely to appear by
116+
# accident
117+
SUCCESS_NOTICE = "All ci/qemu_guest_test.py tests passed"
118+
FAILURE_NOTICE = "Some ci/qemu_guest_test.py tests failed"
119+
# We use apt-get -U here and the apt_dependencies fixture in
120+
# qemu_guest_test.py relies on this.
121+
SCRIPT = f"""sudo -i sh <<EOT
122+
apt-get install -Uy --no-install-recommends python3-pytest
123+
mkdir qcom-deb-images
124+
mount -t 9p qcom-deb-images qcom-deb-images
125+
cd qcom-deb-images
126+
py.test-3 -vvm guest ci/qemu_guest_test.py && echo "{SUCCESS_NOTICE}" || echo "{FAILURE_NOTICE}"
127+
EOT
128+
"""
129+
logged_in_vm.spawn.send(SCRIPT.replace("\r", "\r\n"))
130+
131+
# Match a known string for when pytest starts. Otherwise we catch the echo
132+
# of our own printing of SUCCESS_NOTICE and FAILURE_NOTICE that appears
133+
# before, causing us to falsely believe that it was done. The timeout is
134+
# required to give enough time for the installation of python3-pytest to
135+
# finish.
136+
logged_in_vm.spawn.expect_exact("test session starts", timeout=120)
137+
match = logged_in_vm.spawn.expect_exact(
138+
[SUCCESS_NOTICE, FAILURE_NOTICE], timeout=120
139+
)
140+
assert match == 0, "ci/qemu_guest_test.py tests failed"

pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[tool.pytest.ini_options]
2+
# See ci/qemu_test.py and ci/qemu_test_guest.py for details on arrangements for
3+
# guest tests.
4+
addopts = "-m 'not guest'"
5+
markers = [
6+
"guest: Tests that run from inside a built image"
7+
]

0 commit comments

Comments
 (0)