Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 7f225a2

Browse files
committed
improve tests robustness
1 parent 59b82b9 commit 7f225a2

2 files changed

Lines changed: 18 additions & 20 deletions

File tree

packages/jumpstarter-driver-qemu/jumpstarter_driver_qemu/driver.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from jumpstarter_driver_opendal.driver import FlasherInterface
2222
from jumpstarter_driver_power.driver import PowerInterface, PowerReading
2323
from jumpstarter_driver_pyserial.driver import PySerial
24-
from pydantic import BaseModel, ByteSize, Field, TypeAdapter, validate_call
24+
from pydantic import BaseModel, ByteSize, Field, TypeAdapter, ValidationError, validate_call
2525
from qemu.qmp import QMPClient
2626
from qemu.qmp.protocol import ConnectError, Runstate
2727

@@ -183,9 +183,7 @@ async def on(self) -> None: # noqa: C901
183183

184184
# Resize disk if configured
185185
if self.parent.disk_size:
186-
# Convert QEMU binary format (20G) to Pydantic format (20GiB)
187-
s = self.parent.disk_size
188-
requested = int(TypeAdapter(ByteSize).validate_python(s + "iB" if s[-1] in "kmgtKMGT" else s))
186+
requested = self.parent._parse_size(self.parent.disk_size)
189187

190188
if requested < current_virtual_size:
191189
raise RuntimeError(
@@ -406,24 +404,23 @@ def get_username(self) -> str:
406404
def get_password(self) -> str:
407405
return self.password
408406

409-
def _validate_size(self, size: str) -> None:
410-
"""Validate size string (e.g., '20G', '512M')."""
407+
def _parse_size(self, size: str) -> int:
408+
"""Parse size string (e.g., '20G') to bytes."""
411409
try:
412-
s = size
413-
TypeAdapter(ByteSize).validate_python(s + "iB" if s[-1] in "kmgtKMGT" else s)
414-
except Exception:
410+
return int(TypeAdapter(ByteSize).validate_python(size + "iB" if size[-1] in "kmgtKMGT" else size))
411+
except (ValidationError, IndexError):
415412
raise ValueError(f"Invalid size: '{size}'. Use e.g. '20G', '512M', '2T'") from None
416413

417414
@export
418415
@validate_call(validate_return=True)
419416
def set_disk_size(self, size: str) -> None:
420417
"""Set the disk size for resizing before boot."""
421-
self._validate_size(size)
418+
self._parse_size(size) # Validate
422419
self.disk_size = size
423420

424421
@export
425422
@validate_call(validate_return=True)
426423
def set_memory_size(self, size: str) -> None:
427424
"""Set the memory size for next boot."""
428-
self._validate_size(size)
425+
self._parse_size(size) # Validate
429426
self.mem = size

packages/jumpstarter-driver-qemu/jumpstarter_driver_qemu/driver_test.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import tarfile
66
from pathlib import Path
7+
from types import SimpleNamespace
78
from unittest.mock import AsyncMock, patch
89

910
import pytest
@@ -146,7 +147,7 @@ async def test_resize_insufficient_space_blocked(resize_test):
146147
"""Resize beyond available host space should raise RuntimeError."""
147148
driver, current = resize_test("100G", 10) # requested: 100G, current: 10G
148149

149-
mock_usage = type("U", (), {"free": 5 * 1024**3})() # only 5G free
150+
mock_usage = SimpleNamespace(free=5 * 1024**3) # only 5G free
150151

151152
with patch("jumpstarter_driver_qemu.driver.run_process", side_effect=_mock_qemu_img_info(current)):
152153
with patch("jumpstarter_driver_qemu.driver.shutil.disk_usage", return_value=mock_usage):
@@ -158,20 +159,20 @@ async def test_resize_insufficient_space_blocked(resize_test):
158159
async def test_resize_succeeds(resize_test):
159160
"""Resize should call qemu-img resize with correct size."""
160161
driver, current = resize_test("20G", 10) # requested: 20G, current: 10G
161-
mock_usage = type("U", (), {"free": 50 * 1024**3})()
162+
mock_usage = SimpleNamespace(free=50 * 1024**3)
162163

163164
with patch("jumpstarter_driver_qemu.driver.run_process", side_effect=_mock_qemu_img_info(current)) as mock_run:
164165
with patch("jumpstarter_driver_qemu.driver.shutil.disk_usage", return_value=mock_usage):
165-
with patch("jumpstarter_driver_qemu.driver.Popen"):
166-
try:
166+
# Mock Popen to stop before actually starting QEMU VM
167+
with patch("jumpstarter_driver_qemu.driver.Popen", side_effect=RuntimeError("mock popen")):
168+
with pytest.raises(RuntimeError, match="mock popen"):
167169
await driver.children["power"].on()
168-
except Exception:
169-
pass # Expected to fail at Popen
170170

171-
# Find the resize call
172-
resize_calls = [c for c in mock_run.call_args_list if "resize" in c[0][0]]
171+
# Find the resize call and verify size argument
172+
resize_calls = [c for c in mock_run.call_args_list if "resize" in c.args[0]]
173173
assert resize_calls, "qemu-img resize should be called"
174-
assert resize_calls[0][0][0][-1] == str(20 * 1024**3)
174+
resize_cmd = resize_calls[0].args[0] # ['qemu-img', 'resize', path, size]
175+
assert resize_cmd[-1] == str(20 * 1024**3)
175176

176177

177178
def test_set_disk_size_valid():

0 commit comments

Comments
 (0)