Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

several improvements for tests in Ubuntu 24.10 #276

Merged
merged 8 commits into from
Nov 18, 2024
50 changes: 39 additions & 11 deletions tests/lib/Qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ class QemuMonitor():
READ_TIMEOUT = 2
CONNECT_RETRIES = 60

def __new__(cls, qemu):
# only 1 monitor per qemu machine
if qemu.monitor is None:
qemu.monitor = super().__new__(cls)
return qemu.monitor

def __init__(self, qemu):
self.socket = None
assert qemu.qcmd.monitor_file != None, "Monitor socket file is undefined"
Expand All @@ -312,11 +318,13 @@ def __init__(self, qemu):
break
except Exception as e:
# give some time to make sure socket file is available
print(f'Try to connect to qemu : {qemu.qcmd.monitor_file} : {e}')
time.sleep(1)
self.socket.settimeout(self.READ_TIMEOUT)
# wait for promt
hector-cao marked this conversation as resolved.
Show resolved Hide resolved
print(f'Connected : {qemu.qcmd.monitor_file}, wait for prompt.')
self.wait_prompt()

def recv(self):
def recv_data(self):
msg = ''
try:
while True:
Expand All @@ -327,6 +335,22 @@ def recv(self):
msg += recv_data.decode('utf-8')
except:
pass
return msg

def wait_prompt(self):
msg = self.recv_data()
assert self.DELIMITER_STRING in msg, f'Fail on wait for monitor prompt : {msg}'

def recv(self):
"""
Return an array of messages from qemu process
separated by the prompt string (qemu)
Example:
(qemu) running
(qemu) rebooting
will result in the returned value : [' running', ' rebooting']
"""
msg = self.recv_data()
return msg.split(self.DELIMITER_STRING)

def send_command(self, cmd):
Expand Down Expand Up @@ -481,7 +505,6 @@ class QemuMachineService:
# to run the guest manually
qemu_run_script = """
#!/bin/bash
echo "To connect to the VM : ssh -p {fwd_port} root@localhost"
{cmd_str}
"""

Expand Down Expand Up @@ -511,6 +534,10 @@ def __init__(self,
)
self.qcmd.add_image(self.image_path)
self.qcmd.add_monitor()
# monitor client associated to this machine
# since there could be only one client, we keep track
# of this client instance in the qemu machine object
self.monitor = None
self.qcmd.add_qmp()
if QemuMachineService.QEMU_MACHINE_PORT_FWD not in service_blacklist:
self.fwd_port = util.tcp_port_available()
Expand Down Expand Up @@ -606,7 +633,7 @@ def communicate(self):
"""
Wait for qemu to exit
"""
self.out, self.err = self.proc.communicate()
self.out, self.err = self.proc.communicate(timeout=60)
if self.proc.returncode != 0:
print(self.err.decode())
return self.out, self.err
Expand All @@ -622,17 +649,19 @@ def stop(self):

# self.proc.returncode == None -> not yet terminated

# try to shutdown the VM properly, this is important to avoid
# rootfs corruption if we want to run the guest again
mon = QemuMonitor(self)
mon.powerdown()
try:
# try to shutdown the VM properly, this is important to avoid
# rootfs corruption if we want to run the guest again
# catch exception and ignore it since we are stopping .... no need to fail the test
mon = QemuMonitor(self)
mon.powerdown()

self.communicate()
return
except Exception as e:
pass

print('Qemu process did not shutdown properly, terminate it ...')
print(f'Qemu process did not shutdown properly, terminate it ... ({self.workdir_name})')
# terminate qemu process (SIGTERM)
try:
self.proc.terminate()
Expand Down Expand Up @@ -671,8 +700,7 @@ def write_cmd_to_file(self, fname : str):
cmd_str += f'\"{el}\" '
else:
cmd_str += f'{el} '
script_contents = qemu_run_script.format(fwd_port=self.fwd_port,
cmd_str=cmd_str)
script_contents = qemu_run_script.format(cmd_str=cmd_str)
run_script.write(script_contents)
f = pathlib.Path(fname)
f.chmod(f.stat().st_mode | stat.S_IEXEC)
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/test_stress_boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import util

def test_boot():
def test_stress_boot():
"""
Boot in loop
"""
Expand Down
13 changes: 7 additions & 6 deletions tests/tests/test_stress_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import Qemu
import util

def test_huge_resource_vm(qm):
def test_stress_huge_resource_vm(qm):
"""
Test huge resources (Intel Case ID 007)
"""
Expand All @@ -34,11 +34,12 @@ def test_huge_resource_vm(qm):
qm.qcmd.plugins['memory'].memory = '%dG' % (huge_mem_gb)
qm.run()

ssh = Qemu.QemuSSH(qm)
# huge guest memory -> increase the timeout to give more time to guest to boot
ssh = Qemu.QemuSSH(qm, timeout=100)

qm.stop()

def test_memory_limit_resource_vm(qm):
def test_stress_memory_limit_resource_vm(qm):
"""
Test memory limit resource (No Intel Case)
"""
Expand All @@ -54,7 +55,7 @@ def test_memory_limit_resource_vm(qm):
qm.stop()


def test_max_vcpus(qm):
def test_stress_max_vcpus(qm):
"""
Test max vcpus (No Intel Case ID)
"""
Expand All @@ -65,12 +66,12 @@ def test_max_vcpus(qm):
qm.qcmd.plugins['cpu'].nb_cores = num_cpus
qm.run()

ssh = Qemu.QemuSSH(qm)
ssh = Qemu.QemuSSH(qm, timeout=100)

qm.stop()


def test_max_guests():
def test_stress_max_guests():
"""
Test max guests (No Intel Case ID)
"""
Expand Down
22 changes: 13 additions & 9 deletions tests/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,40 @@ commands_pre =

[testenv:test_guest]
commands =
python3 -m pytest -s -v --junitxml=test_guest_report.xml -k test_guest
python3 -m pytest -s -v --junitxml=test_guest_report.xml --ignore=tests/guest -k test_guest

[testenv:test_host]
commands =
python3 -m pytest -s -v --junitxml=test_host_report.xml -k test_host
python3 -m pytest -s -v --junitxml=test_host_report.xml --ignore=tests/guest -k test_host

[testenv:test_boot]
commands =
python3 -m pytest -s -v --junitxml=test_boot_report.xml -k test_boot
python3 -m pytest -s -v --junitxml=test_boot_report.xml --ignore=tests/guest -k test_boot

[testenv:test_perf]
commands =
python3 -m pytest -s -v --junitxml=test_perf_report.xml -k test_perf
python3 -m pytest -s -v --junitxml=test_perf_report.xml --ignore=tests/guest -k test_perf

[testenv:test_quote]
commands =
python3 -m pytest -s -v --junitxml=test_quote_report.xml -k test_quote
python3 -m pytest -s -v --junitxml=test_quote_report.xml --ignore=tests/guest -k test_quote

[testenv:test_stress]
commands =
python3 -m pytest -s -v --junitxml=test_stress_report.xml -k test_stress
python3 -m pytest -s -v --junitxml=test_stress_report.xml --ignore=tests/guest -k test_stress

[testenv:test_all_except_perf]
commands =
python3 -m pytest -s -v --junitxml=test_all_report.xml --ignore=tests/guest -k 'not test_perf'

[testenv:test_all]
commands =
python3 -m pytest -s -v --junitxml=test_all_report.xml
python3 -m pytest -s -v --junitxml=test_all_report.xml --ignore=tests/guest

[testenv:test_specify]
commands =
python3 -m pytest -s -v --junitxml=test_specify_report.xml -k {posargs}
python3 -m pytest -s -v --junitxml=test_specify_report.xml --ignore=tests/guest -k {posargs}

[testenv:collect_tests]
commands =
python3 -m pytest -s -v --collect-only -k {posargs}
python3 -m pytest -s -v --collect-only --ignore=tests/guest -k {posargs}