mirror of
https://github.com/esphome/esphome.git
synced 2025-10-30 22:53:59 +00:00
Fix dashboard dns lookup delay
This commit is contained in:
@@ -594,3 +594,90 @@ def test_resolve_ip_address_sorting() -> None:
|
||||
assert result[0][4][0] == "2001:db8::1" # IPv6 (preference 1)
|
||||
assert result[1][4][0] == "192.168.1.100" # IPv4 (preference 2)
|
||||
assert result[2][4][0] == "fe80::1" # Link-local no scope (preference 3)
|
||||
|
||||
|
||||
def test_resolve_ip_address_with_cache() -> None:
|
||||
"""Test that the cache is used when provided."""
|
||||
from esphome.address_cache import AddressCache
|
||||
|
||||
cache = AddressCache(
|
||||
mdns_cache={"test.local": ["192.168.1.100", "192.168.1.101"]},
|
||||
dns_cache={
|
||||
"example.com": ["93.184.216.34", "2606:2800:220:1:248:1893:25c8:1946"]
|
||||
},
|
||||
)
|
||||
|
||||
# Test mDNS cache hit
|
||||
result = helpers.resolve_ip_address("test.local", 6053, address_cache=cache)
|
||||
|
||||
# Should return cached addresses without calling resolver
|
||||
assert len(result) == 2
|
||||
assert result[0][4][0] == "192.168.1.100"
|
||||
assert result[1][4][0] == "192.168.1.101"
|
||||
|
||||
# Test DNS cache hit
|
||||
result = helpers.resolve_ip_address("example.com", 6053, address_cache=cache)
|
||||
|
||||
# Should return cached addresses with IPv6 first due to preference
|
||||
assert len(result) == 2
|
||||
assert result[0][4][0] == "2606:2800:220:1:248:1893:25c8:1946" # IPv6 first
|
||||
assert result[1][4][0] == "93.184.216.34" # IPv4 second
|
||||
|
||||
|
||||
def test_resolve_ip_address_cache_miss() -> None:
|
||||
"""Test that resolver is called when not in cache."""
|
||||
from esphome.address_cache import AddressCache
|
||||
|
||||
cache = AddressCache(mdns_cache={"other.local": ["192.168.1.200"]})
|
||||
|
||||
mock_addr_info = AddrInfo(
|
||||
family=socket.AF_INET,
|
||||
type=socket.SOCK_STREAM,
|
||||
proto=socket.IPPROTO_TCP,
|
||||
sockaddr=IPv4Sockaddr(address="192.168.1.100", port=6053),
|
||||
)
|
||||
|
||||
with patch("esphome.resolver.AsyncResolver") as MockResolver:
|
||||
mock_resolver = MockResolver.return_value
|
||||
mock_resolver.resolve.return_value = [mock_addr_info]
|
||||
|
||||
result = helpers.resolve_ip_address("test.local", 6053, address_cache=cache)
|
||||
|
||||
# Should call resolver since test.local is not in cache
|
||||
MockResolver.assert_called_once_with(["test.local"], 6053)
|
||||
assert len(result) == 1
|
||||
assert result[0][4][0] == "192.168.1.100"
|
||||
|
||||
|
||||
def test_resolve_ip_address_mixed_cached_uncached() -> None:
|
||||
"""Test resolution with mix of cached and uncached hosts."""
|
||||
from esphome.address_cache import AddressCache
|
||||
|
||||
cache = AddressCache(mdns_cache={"cached.local": ["192.168.1.50"]})
|
||||
|
||||
mock_addr_info = AddrInfo(
|
||||
family=socket.AF_INET,
|
||||
type=socket.SOCK_STREAM,
|
||||
proto=socket.IPPROTO_TCP,
|
||||
sockaddr=IPv4Sockaddr(address="192.168.1.100", port=6053),
|
||||
)
|
||||
|
||||
with patch("esphome.resolver.AsyncResolver") as MockResolver:
|
||||
mock_resolver = MockResolver.return_value
|
||||
mock_resolver.resolve.return_value = [mock_addr_info]
|
||||
|
||||
# Pass a list with cached IP, cached hostname, and uncached hostname
|
||||
result = helpers.resolve_ip_address(
|
||||
["192.168.1.10", "cached.local", "uncached.local"],
|
||||
6053,
|
||||
address_cache=cache,
|
||||
)
|
||||
|
||||
# Should only resolve uncached.local
|
||||
MockResolver.assert_called_once_with(["uncached.local"], 6053)
|
||||
|
||||
# Results should include all addresses
|
||||
addresses = [r[4][0] for r in result]
|
||||
assert "192.168.1.10" in addresses # Direct IP
|
||||
assert "192.168.1.50" in addresses # From cache
|
||||
assert "192.168.1.100" in addresses # From resolver
|
||||
|
||||
@@ -10,6 +10,7 @@ from unittest.mock import Mock, patch
|
||||
import pytest
|
||||
|
||||
from esphome.__main__ import choose_upload_log_host
|
||||
from esphome.address_cache import AddressCache
|
||||
from esphome.const import CONF_BROKER, CONF_MQTT, CONF_USE_ADDRESS, CONF_WIFI
|
||||
from esphome.core import CORE
|
||||
|
||||
@@ -510,3 +511,73 @@ def test_choose_upload_log_host_no_address_with_ota_config() -> None:
|
||||
show_api=False,
|
||||
)
|
||||
assert result == []
|
||||
|
||||
|
||||
def test_address_cache_from_cli_args() -> None:
|
||||
"""Test parsing address cache from CLI arguments."""
|
||||
# Test empty lists
|
||||
cache = AddressCache.from_cli_args([], [])
|
||||
assert cache.mdns_cache == {}
|
||||
assert cache.dns_cache == {}
|
||||
|
||||
# Test single entry with single IP
|
||||
cache = AddressCache.from_cli_args(
|
||||
["host.local=192.168.1.1"], ["example.com=10.0.0.1"]
|
||||
)
|
||||
assert cache.mdns_cache == {"host.local": ["192.168.1.1"]}
|
||||
assert cache.dns_cache == {"example.com": ["10.0.0.1"]}
|
||||
|
||||
# Test multiple IPs
|
||||
cache = AddressCache.from_cli_args(["host.local=192.168.1.1,192.168.1.2"], [])
|
||||
assert cache.mdns_cache == {"host.local": ["192.168.1.1", "192.168.1.2"]}
|
||||
|
||||
# Test multiple entries
|
||||
cache = AddressCache.from_cli_args(
|
||||
["host1.local=192.168.1.1", "host2.local=192.168.1.2"],
|
||||
["example.com=10.0.0.1", "test.org=10.0.0.2,10.0.0.3"],
|
||||
)
|
||||
assert cache.mdns_cache == {
|
||||
"host1.local": ["192.168.1.1"],
|
||||
"host2.local": ["192.168.1.2"],
|
||||
}
|
||||
assert cache.dns_cache == {
|
||||
"example.com": ["10.0.0.1"],
|
||||
"test.org": ["10.0.0.2", "10.0.0.3"],
|
||||
}
|
||||
|
||||
# Test with IPv6
|
||||
cache = AddressCache.from_cli_args(["host.local=2001:db8::1,fe80::1"], [])
|
||||
assert cache.mdns_cache == {"host.local": ["2001:db8::1", "fe80::1"]}
|
||||
|
||||
# Test invalid format (should be skipped with warning)
|
||||
with patch("esphome.address_cache._LOGGER") as mock_logger:
|
||||
cache = AddressCache.from_cli_args(["invalid_format"], [])
|
||||
assert cache.mdns_cache == {}
|
||||
mock_logger.warning.assert_called_once()
|
||||
|
||||
|
||||
def test_address_cache_get_methods() -> None:
|
||||
"""Test the AddressCache get methods."""
|
||||
cache = AddressCache(
|
||||
mdns_cache={"test.local": ["192.168.1.1"]},
|
||||
dns_cache={"example.com": ["10.0.0.1"]},
|
||||
)
|
||||
|
||||
# Test mDNS lookup
|
||||
assert cache.get_mdns_addresses("test.local") == ["192.168.1.1"]
|
||||
assert cache.get_mdns_addresses("other.local") is None
|
||||
|
||||
# Test DNS lookup
|
||||
assert cache.get_dns_addresses("example.com") == ["10.0.0.1"]
|
||||
assert cache.get_dns_addresses("other.com") is None
|
||||
|
||||
# Test automatic selection based on domain
|
||||
assert cache.get_addresses("test.local") == ["192.168.1.1"]
|
||||
assert cache.get_addresses("example.com") == ["10.0.0.1"]
|
||||
assert cache.get_addresses("unknown.local") is None
|
||||
assert cache.get_addresses("unknown.com") is None
|
||||
|
||||
# Test has_cache
|
||||
assert cache.has_cache() is True
|
||||
empty_cache = AddressCache()
|
||||
assert empty_cache.has_cache() is False
|
||||
|
||||
Reference in New Issue
Block a user