Skip to content

Commit 66fc7d7

Browse files
authored
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
1 parent 9cc45f6 commit 66fc7d7

File tree

4 files changed

+81
-5
lines changed

4 files changed

+81
-5
lines changed

tests/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@
99
logger = logging.getLogger(__name__)
1010

1111

12+
@pytest.fixture(scope="function")
13+
def without_internet(strategy):
14+
default_nic = strategy.qemu.nic
15+
if strategy.status.name == "shell":
16+
strategy.transition("off")
17+
strategy.qemu.nic = "user,net=192.168.76.0/24,dhcpstart=192.168.76.10,restrict=yes"
18+
strategy.transition("shell")
19+
yield
20+
strategy.transition("off")
21+
strategy.qemu.nic = default_nic
22+
23+
1224
@pytest.fixture(autouse=True, scope="module")
1325
def restart_qemu(strategy):
1426
"""Use fresh QEMU instance for each module."""

tests/qemu_shell_strategy.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ def transition(self, status, *, step): # pylint: disable=redefined-outer-name
5656
step.skip("nothing to do")
5757
return # nothing to do
5858
elif status == Status.off:
59-
self.target.activate(self.qemu)
60-
self.qemu.off()
59+
self.target.deactivate(self.qemu)
6160
self.target.deactivate(self.shell)
6261
elif status == Status.shell:
6362
self.target.activate(self.qemu)

tests/requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
labgrid==23.0.3
1+
labgrid==23.0.6
22
pytest==7.2.2
3-
pytest-dependency==0.5.1
4-
pytest-timeout==2.2.0
3+
pytest-dependency==0.6.0
4+
pytest-timeout==2.3.1

tests/smoke_test/test_offline.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import logging
2+
from time import sleep
3+
4+
import pytest
5+
from labgrid.driver import ExecutionError
6+
7+
_LOGGER = logging.getLogger(__name__)
8+
9+
10+
def _check_connectivity(shell, *, connected):
11+
for target in ["home-assistant.io", "1.1.1.1"]:
12+
try:
13+
output = shell.run_check(f"ping {target}")
14+
if f"{target} is alive!" in output:
15+
if connected:
16+
return True
17+
else:
18+
raise AssertionError(f"expecting disconnected but {target} is alive")
19+
except ExecutionError as exc:
20+
if not connected:
21+
stdout = "\n".join(exc.stdout)
22+
assert ("Network is unreachable" in stdout
23+
or "bad address" in stdout
24+
or "No response" in stdout)
25+
26+
if connected:
27+
raise AssertionError(f"expecting connected but all targets are down")
28+
29+
30+
@pytest.mark.timeout(300) # takes quite a while also because of 90s NTP sync timeout
31+
@pytest.mark.usefixtures("without_internet")
32+
def test_ha_runs_offline(shell):
33+
def check_container_running(container_name):
34+
out = shell.run_check(
35+
f"docker container inspect -f '{{{{.State.Status}}}}' {container_name} || true"
36+
)
37+
return "running" in out
38+
39+
# wait for supervisor to create network
40+
while True:
41+
if check_container_running("hassio_supervisor"):
42+
nm_conns = shell.run_check('nmcli con show')
43+
if "Supervisor" in " ".join(nm_conns):
44+
break
45+
sleep(1)
46+
47+
# To simulate situation where HAOS is not connected to internet, we need to add
48+
# default gateway to the supervisor connection. So we add a default route to
49+
# a non-existing IP address in the VM's subnet. Maybe there is a better way?
50+
shell.run_check('nmcli con modify "Supervisor enp0s3" ipv4.addresses "192.168.76.10/24" '
51+
'&& nmcli con modify "Supervisor enp0s3" ipv4.gateway 192.168.76.1 '
52+
'&& nmcli device reapply enp0s3')
53+
54+
_check_connectivity(shell, connected=False)
55+
56+
for _ in range(60):
57+
if check_container_running("homeassistant") and check_container_running("hassio_cli"):
58+
break
59+
sleep(1)
60+
else:
61+
shell.run_check("docker logs hassio_supervisor")
62+
raise AssertionError("homeassistant or hassio_cli not running after 60s")
63+
64+
web_index = shell.run_check("curl http://localhost:8123")
65+
assert "</html>" in " ".join(web_index)

0 commit comments

Comments
 (0)