Add tests for package errors (#103902)
This commit is contained in:
parent
74bf255da6
commit
be2cee228c
27 changed files with 160 additions and 55 deletions
21
tests/fixtures/core/config/package_errors/packages/configuration.yaml
vendored
Normal file
21
tests/fixtures/core/config/package_errors/packages/configuration.yaml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# adr007_1 should be a dict, this will cause a package error
|
||||||
|
adr_0007_1:
|
||||||
|
- host: blah.com
|
||||||
|
|
||||||
|
homeassistant:
|
||||||
|
packages:
|
||||||
|
pack_1:
|
||||||
|
# This is correct, but root config is wrong
|
||||||
|
adr_0007_1:
|
||||||
|
port: 8080
|
||||||
|
pack_2:
|
||||||
|
# Should not be a list
|
||||||
|
adr_0007_2:
|
||||||
|
- host: blah.com
|
||||||
|
pack_3:
|
||||||
|
# Host duplicated in pack_4
|
||||||
|
adr_0007_3:
|
||||||
|
host: blah.com
|
||||||
|
pack_4:
|
||||||
|
adr_0007_3:
|
||||||
|
host: blah.com
|
7
tests/fixtures/core/config/package_errors/packages_include_dir_named/configuration.yaml
vendored
Normal file
7
tests/fixtures/core/config/package_errors/packages_include_dir_named/configuration.yaml
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# adr007_1 should be a dict, this will cause a package error
|
||||||
|
adr_0007_1:
|
||||||
|
- host: blah.com
|
||||||
|
|
||||||
|
homeassistant:
|
||||||
|
# Load packages
|
||||||
|
packages: !include_dir_named integrations
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This is correct, but root config is wrong
|
||||||
|
adr_0007_1:
|
||||||
|
port: 8080
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Should not be a list
|
||||||
|
adr_0007_2:
|
||||||
|
- host: blah.com
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Host duplicated in adr_0007_3_2.yaml
|
||||||
|
adr_0007_3:
|
||||||
|
host: blah.com
|
|
@ -0,0 +1,2 @@
|
||||||
|
adr_0007_3:
|
||||||
|
host: blah.com
|
|
@ -1,45 +1,59 @@
|
||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
# name: test_component_config_validation_error[basic]
|
# name: test_component_config_validation_error[basic]
|
||||||
list([
|
list([
|
||||||
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/basic/configuration.yaml, line 6). ",
|
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/component_validation/basic/configuration.yaml, line 6). ",
|
||||||
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/basic/configuration.yaml, line 9). ",
|
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/component_validation/basic/configuration.yaml, line 9). ",
|
||||||
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
||||||
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See <BASE_PATH>/fixtures/core/config/basic/configuration.yaml, line 20). ",
|
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See <BASE_PATH>/fixtures/core/config/component_validation/basic/configuration.yaml, line 20). ",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
# name: test_component_config_validation_error[basic_include]
|
# name: test_component_config_validation_error[basic_include]
|
||||||
list([
|
list([
|
||||||
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/basic_include/integrations/iot_domain.yaml, line 5). ",
|
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/component_validation/basic_include/integrations/iot_domain.yaml, line 5). ",
|
||||||
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/basic_include/integrations/iot_domain.yaml, line 8). ",
|
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/component_validation/basic_include/integrations/iot_domain.yaml, line 8). ",
|
||||||
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
||||||
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See <BASE_PATH>/fixtures/core/config/basic_include/configuration.yaml, line 4). ",
|
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See <BASE_PATH>/fixtures/core/config/component_validation/basic_include/configuration.yaml, line 4). ",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
# name: test_component_config_validation_error[include_dir_list]
|
# name: test_component_config_validation_error[include_dir_list]
|
||||||
list([
|
list([
|
||||||
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/include_dir_list/iot_domain/iot_domain_2.yaml, line 2). ",
|
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/component_validation/include_dir_list/iot_domain/iot_domain_2.yaml, line 2). ",
|
||||||
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/include_dir_list/iot_domain/iot_domain_3.yaml, line 2). ",
|
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/component_validation/include_dir_list/iot_domain/iot_domain_3.yaml, line 2). ",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
# name: test_component_config_validation_error[include_dir_merge_list]
|
# name: test_component_config_validation_error[include_dir_merge_list]
|
||||||
list([
|
list([
|
||||||
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/include_dir_merge_list/iot_domain/iot_domain_2.yaml, line 2). ",
|
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/component_validation/include_dir_merge_list/iot_domain/iot_domain_2.yaml, line 2). ",
|
||||||
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/include_dir_merge_list/iot_domain/iot_domain_2.yaml, line 5). ",
|
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/component_validation/include_dir_merge_list/iot_domain/iot_domain_2.yaml, line 5). ",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
# name: test_component_config_validation_error[packages]
|
# name: test_component_config_validation_error[packages]
|
||||||
list([
|
list([
|
||||||
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/packages/configuration.yaml, line 11). ",
|
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/component_validation/packages/configuration.yaml, line 11). ",
|
||||||
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/packages/configuration.yaml, line 16). ",
|
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/component_validation/packages/configuration.yaml, line 16). ",
|
||||||
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
||||||
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See ?, line ?). ",
|
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See ?, line ?). ",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
# name: test_component_config_validation_error[packages_include_dir_named]
|
# name: test_component_config_validation_error[packages_include_dir_named]
|
||||||
list([
|
list([
|
||||||
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/packages_include_dir_named/integrations/iot_domain.yaml, line 6). ",
|
"Invalid config for [iot_domain.non_adr_0007]: expected str for dictionary value @ data['option1']. Got 123. (See <BASE_PATH>/fixtures/core/config/component_validation/packages_include_dir_named/integrations/iot_domain.yaml, line 6). ",
|
||||||
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/packages_include_dir_named/integrations/iot_domain.yaml, line 9). ",
|
"Invalid config for [iot_domain]: required key not provided @ data['platform']. Got None. (See <BASE_PATH>/fixtures/core/config/component_validation/packages_include_dir_named/integrations/iot_domain.yaml, line 9). ",
|
||||||
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
"Invalid config for [adr_0007_2]: required key not provided @ data['adr_0007_2']['host']. Got None. (See ?, line ?). ",
|
||||||
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See ?, line ?). ",
|
"Invalid config for [adr_0007_3]: expected int for dictionary value @ data['adr_0007_3']['port']. Got 'foo'. (See ?, line ?). ",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_package_merge_error[packages]
|
||||||
|
list([
|
||||||
|
'Package pack_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:9). ',
|
||||||
|
'Package pack_2 setup failed. Integration adr_0007_2 cannot be merged. Expected a dict. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:13). ',
|
||||||
|
"Package pack_4 setup failed. Integration adr_0007_3 has duplicate key 'host' (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:20). ",
|
||||||
|
])
|
||||||
|
# ---
|
||||||
|
# name: test_package_merge_error[packages_include_dir_named]
|
||||||
|
list([
|
||||||
|
'Package adr_0007_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_1.yaml:2). ',
|
||||||
|
'Package adr_0007_2 setup failed. Integration adr_0007_2 cannot be merged. Expected a dict. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_2.yaml:2). ',
|
||||||
|
"Package adr_0007_3_2 setup failed. Integration adr_0007_3 has duplicate key 'host' (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_3_2.yaml:1). ",
|
||||||
|
])
|
||||||
|
# ---
|
||||||
|
|
|
@ -33,7 +33,7 @@ from homeassistant.core import ConfigSource, HomeAssistant, HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv, issue_registry as ir
|
from homeassistant.helpers import config_validation as cv, issue_registry as ir
|
||||||
import homeassistant.helpers.check_config as check_config
|
import homeassistant.helpers.check_config as check_config
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.loader import async_get_integration
|
from homeassistant.loader import Integration, async_get_integration
|
||||||
from homeassistant.util.unit_system import (
|
from homeassistant.util.unit_system import (
|
||||||
_CONF_UNIT_SYSTEM_US_CUSTOMARY,
|
_CONF_UNIT_SYSTEM_US_CUSTOMARY,
|
||||||
METRIC_SYSTEM,
|
METRIC_SYSTEM,
|
||||||
|
@ -94,6 +94,66 @@ def teardown():
|
||||||
os.remove(SAFE_MODE_PATH)
|
os.remove(SAFE_MODE_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
IOT_DOMAIN_PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({vol.Remove("old"): str})
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def mock_iot_domain_integration(hass: HomeAssistant) -> Integration:
|
||||||
|
"""Mock an integration which provides an IoT domain."""
|
||||||
|
comp_platform_schema = cv.PLATFORM_SCHEMA.extend({vol.Remove("old"): str})
|
||||||
|
comp_platform_schema_base = comp_platform_schema.extend({}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
return mock_integration(
|
||||||
|
hass,
|
||||||
|
MockModule(
|
||||||
|
"iot_domain",
|
||||||
|
platform_schema_base=comp_platform_schema_base,
|
||||||
|
platform_schema=comp_platform_schema,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def mock_non_adr_0007_integration(hass) -> None:
|
||||||
|
"""Mock a non-ADR-0007 compliant integration with iot_domain platform.
|
||||||
|
|
||||||
|
The integration allows setting up iot_domain entities under the iot_domain's
|
||||||
|
configuration key
|
||||||
|
"""
|
||||||
|
|
||||||
|
test_platform_schema = IOT_DOMAIN_PLATFORM_SCHEMA.extend({"option1": str})
|
||||||
|
mock_platform(
|
||||||
|
hass,
|
||||||
|
"non_adr_0007.iot_domain",
|
||||||
|
MockPlatform(platform_schema=test_platform_schema),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def mock_adr_0007_integrations(hass) -> list[Integration]:
|
||||||
|
"""Mock ADR-0007 compliant integrations."""
|
||||||
|
integrations = []
|
||||||
|
for domain in ["adr_0007_1", "adr_0007_2", "adr_0007_3"]:
|
||||||
|
adr_0007_config_schema = vol.Schema(
|
||||||
|
{
|
||||||
|
domain: vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required("host"): str,
|
||||||
|
vol.Required("port", default=8080): int,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
extra=vol.ALLOW_EXTRA,
|
||||||
|
)
|
||||||
|
integrations.append(
|
||||||
|
mock_integration(
|
||||||
|
hass,
|
||||||
|
MockModule(domain, config_schema=adr_0007_config_schema),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return integrations
|
||||||
|
|
||||||
|
|
||||||
async def test_create_default_config(hass: HomeAssistant) -> None:
|
async def test_create_default_config(hass: HomeAssistant) -> None:
|
||||||
"""Test creation of default config."""
|
"""Test creation of default config."""
|
||||||
assert not os.path.isfile(YAML_PATH)
|
assert not os.path.isfile(YAML_PATH)
|
||||||
|
@ -1425,52 +1485,16 @@ async def test_component_config_validation_error(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
config_dir: str,
|
config_dir: str,
|
||||||
|
mock_iot_domain_integration: Integration,
|
||||||
|
mock_non_adr_0007_integration: None,
|
||||||
|
mock_adr_0007_integrations: list[Integration],
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test schema error in component."""
|
"""Test schema error in component."""
|
||||||
comp_platform_schema = cv.PLATFORM_SCHEMA.extend({vol.Remove("old"): str})
|
|
||||||
comp_platform_schema_base = comp_platform_schema.extend({}, extra=vol.ALLOW_EXTRA)
|
|
||||||
|
|
||||||
# Mock an integration which provides an IoT domain
|
|
||||||
mock_integration(
|
|
||||||
hass,
|
|
||||||
MockModule(
|
|
||||||
"iot_domain",
|
|
||||||
platform_schema_base=comp_platform_schema_base,
|
|
||||||
platform_schema=comp_platform_schema,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Mock a non-ADR-0007 compliant integration which allows setting up
|
|
||||||
# iot_domain entities under the iot_domain's configuration key
|
|
||||||
test_platform_schema = comp_platform_schema.extend({"option1": str})
|
|
||||||
mock_platform(
|
|
||||||
hass,
|
|
||||||
"non_adr_0007.iot_domain",
|
|
||||||
MockPlatform(platform_schema=test_platform_schema),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Mock an ADR-0007 compliant integration
|
|
||||||
for domain in ["adr_0007_1", "adr_0007_2", "adr_0007_3"]:
|
|
||||||
adr_0007_config_schema = vol.Schema(
|
|
||||||
{
|
|
||||||
domain: vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required("host"): str,
|
|
||||||
vol.Required("port", default=8080): int,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
extra=vol.ALLOW_EXTRA,
|
|
||||||
)
|
|
||||||
mock_integration(
|
|
||||||
hass,
|
|
||||||
MockModule(domain, config_schema=adr_0007_config_schema),
|
|
||||||
)
|
|
||||||
|
|
||||||
base_path = os.path.dirname(__file__)
|
base_path = os.path.dirname(__file__)
|
||||||
hass.config.config_dir = os.path.join(
|
hass.config.config_dir = os.path.join(
|
||||||
base_path, "fixtures", "core", "config", config_dir
|
base_path, "fixtures", "core", "config", "component_validation", config_dir
|
||||||
)
|
)
|
||||||
config = await config_util.async_hass_config_yaml(hass)
|
config = await config_util.async_hass_config_yaml(hass)
|
||||||
|
|
||||||
|
@ -1488,3 +1512,31 @@ async def test_component_config_validation_error(
|
||||||
if record.levelno == logging.ERROR
|
if record.levelno == logging.ERROR
|
||||||
]
|
]
|
||||||
assert error_records == snapshot
|
assert error_records == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"config_dir",
|
||||||
|
["packages", "packages_include_dir_named"],
|
||||||
|
)
|
||||||
|
async def test_package_merge_error(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
config_dir: str,
|
||||||
|
mock_iot_domain_integration: Integration,
|
||||||
|
mock_non_adr_0007_integration: None,
|
||||||
|
mock_adr_0007_integrations: list[Integration],
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test schema error in component."""
|
||||||
|
base_path = os.path.dirname(__file__)
|
||||||
|
hass.config.config_dir = os.path.join(
|
||||||
|
base_path, "fixtures", "core", "config", "package_errors", config_dir
|
||||||
|
)
|
||||||
|
await config_util.async_hass_config_yaml(hass)
|
||||||
|
|
||||||
|
error_records = [
|
||||||
|
record.message.replace(base_path, "<BASE_PATH>")
|
||||||
|
for record in caplog.get_records("call")
|
||||||
|
if record.levelno == logging.ERROR
|
||||||
|
]
|
||||||
|
assert error_records == snapshot
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue