Files
home-assistant-operating-sy…/tests/qemu_shell_strategy.py
Jan Čermák 66fc7d7e2a Test landing page is reachable without internet connection (#3499)
* Test landing page is reachable without internet connection

Add test that checks user is able to access the landing page even when HAOS has
no internet connection. We still need some sort of outgoing connectivity, so
outgoing connection attempts don't end up with "network is unreachable". To
simulate this, restricted network is created for the QEMU instance used in the
test, and when everything is started, unresponsive default gateway is added.

This intents to test regression that was fixed by
home-assistant/supervisor#5204, Supervisor 2024.7.0+ is thus needed for this
test to pass.

* Bump requirements for tests
2024-08-06 11:02:59 +02:00

68 lines
2.2 KiB
Python

import enum
import os
import attr
from labgrid import target_factory, step
from labgrid.driver import ShellDriver
from labgrid.strategy import Strategy, StrategyError
class Status(enum.Enum):
unknown = 0
off = 1
shell = 2
@target_factory.reg_driver
@attr.s(eq=False)
class CustomTimeoutShellDriver(ShellDriver):
"""ShellDriver with a config-customizable timeout for run and run_check."""
command_timeout = attr.ib(default=30, validator=attr.validators.instance_of(int))
def run(self, cmd: str, *, timeout=None, codec="utf-8", decodeerrors="strict"):
return super().run(cmd, timeout=timeout or self.command_timeout, codec=codec, decodeerrors=decodeerrors)
def run_check(self, cmd: str, *, timeout=None, codec="utf-8", decodeerrors="strict"):
return super().run_check(cmd, timeout=timeout or self.command_timeout, codec=codec, decodeerrors=decodeerrors)
@target_factory.reg_driver
@attr.s(eq=False)
class QEMUShellStrategy(Strategy):
"""Strategy for starting a QEMU VM and running shell commands within it."""
bindings = {
"qemu": "QEMUDriver",
"shell": "CustomTimeoutShellDriver",
}
status = attr.ib(default=Status.unknown)
def __attrs_post_init__(self):
super().__attrs_post_init__()
if "-accel kvm" in self.qemu.extra_args and os.environ.get("NO_KVM"):
self.qemu.extra_args = self.qemu.extra_args.replace(
"-accel kvm", ""
).strip()
@step(args=["status"])
def transition(self, status, *, step): # pylint: disable=redefined-outer-name
if not isinstance(status, Status):
status = Status[status]
if status == Status.unknown:
raise StrategyError(f"can not transition to {status}")
elif status == self.status:
step.skip("nothing to do")
return # nothing to do
elif status == Status.off:
self.target.deactivate(self.qemu)
self.target.deactivate(self.shell)
elif status == Status.shell:
self.target.activate(self.qemu)
self.qemu.on()
self.target.activate(self.shell)
else:
raise StrategyError(f"no transition found from {self.status} to {status}")
self.status = status