Add a series of unit tests which try to cover somewhat systematically the possible inputs and what we finally get at the exit of the Binding constructor. Running the assumption that any (valid) YAML binding file is something we can make a Binding instance with: - check which properties are defined at which level (binding, child-binding, grandchild-binding, etc) and their specifications once the binding is initialized - check how including bindings are permitted to specialize the specifications of inherited properties - check the rules applied when overwriting a binding's description or compatible string (at the binding, child-binding, etc, levels) Some tests covering known issues are disabled by default: - this permits to document these issues - while not causing CI errors (when running the python-devicetree unit tests) - enabling these tests without causing errors should allow us to consider the related issues are fixed Signed-off-by: Christophe Dufaza <chris@openmarl.org>
1160 lines
43 KiB
Python
1160 lines
43 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright (c) 2024 Christophe Dufaza
|
|
|
|
"""Unit tests dedicated to edtlib.Binding objects initialization.
|
|
|
|
Running the assumption that any (valid) YAML binding file is
|
|
something we can make a Binding instance with:
|
|
- check which properties are defined at which level (binding, child-binding,
|
|
grandchild-binding, etc) and their specifications once the binding
|
|
is initialized
|
|
- check how including bindings are permitted to specialize
|
|
the specifications of inherited properties
|
|
- check the rules applied when overwriting a binding's description
|
|
or compatible string (at the binding, child-binding, etc, levels)
|
|
|
|
At any level, an including binding is permitted to:
|
|
- filter the properties it chooses to inherit with either "property:allowlist"
|
|
or "property:blocklist" but not both
|
|
- extend inherited properties:
|
|
- override (implicit or) explicit "required: false" with "required: true"
|
|
- add constraints to the possible value(s) of a property with "const:"
|
|
or "enum:"
|
|
- add a "default:" value to a property
|
|
- add or overwrite a property's "description:"; when overwritten multiple
|
|
times by several included binding files, "include:"ed first "wins"
|
|
- define new properties
|
|
|
|
At any level, an including binding is NOT permitted to:
|
|
- remove a requirement by overriding "required: true" with "required: false"
|
|
- change existing constrains applied to the possible values of
|
|
an inherited property with "const:" or "enum:"
|
|
- change the "default:" value of an inherited property
|
|
- change the "type:" of an inherited property
|
|
|
|
Rules applying to bindings' descriptions and compatible strings:
|
|
- included files can't overwrite the description or compatible string set
|
|
by the including binding (despite that "description:" appears before
|
|
"include:"): this seems consistent, the top-level binding file "wins"
|
|
- an including binding can overwrite descriptions and compatible strings
|
|
inherited at the child-binding levels: this seems consistent,
|
|
the top-level binding file "wins"
|
|
- when we include multiple files overwriting a description or compatible
|
|
string inherited at the child-binding levels, order of inclusion matters,
|
|
the first "wins"; this is consistent with property descriptions
|
|
|
|
For all tests, the entry point is a Binding instance initialized
|
|
by loading the YAML file which represents the test case: our focus here
|
|
really is what happens when we (recursively) call Binding's constructor,
|
|
independently of any actual devicetree model (edtlib.EDT instance).
|
|
"""
|
|
|
|
# pylint: disable=too-many-statements
|
|
|
|
import contextlib
|
|
import os
|
|
from collections.abc import Generator
|
|
from typing import Any
|
|
|
|
import pytest
|
|
from devicetree import edtlib
|
|
|
|
YAML_KNOWN_BASE_BINDINGS: dict[str, str] = {
|
|
# Base properties, bottom of the diamond test case.
|
|
"base.yaml": "test-bindings-init/base.yaml",
|
|
# Amended properties, left (first) "include:" in the diamond test case.
|
|
"base_amend.yaml": "test-bindings-init/base_amend.yaml",
|
|
# Amended properties, right (last) "include:" in the diamond test case.
|
|
"thing.yaml": "test-bindings-init/thing.yaml",
|
|
# Used for testing property filters when "A includes B includes C".
|
|
"simple.yaml": "test-bindings-init/simple.yaml",
|
|
"simple_inherit.yaml": "test-bindings-init/simple_inherit.yaml",
|
|
"simple_allowlist.yaml": "test-bindings-init/simple_allowlist.yaml",
|
|
"simple_blocklist.yaml": "test-bindings-init/simple_blocklist.yaml",
|
|
# Test applied rules for compatible strings and descriptions.
|
|
"compat_desc_base.yaml": "test-bindings-init/compat_desc_base.yaml",
|
|
"compat_desc.yaml": "test-bindings-init/compat_desc.yaml",
|
|
}
|
|
|
|
|
|
def load_binding(path: str) -> edtlib.Binding:
|
|
"""Load YAML file as Binding instance,
|
|
using YAML_BASE to resolve includes.
|
|
|
|
Args:
|
|
path: Path relative to ZEPHYR_BASE/scripts/dts/python-devicetree/tests.
|
|
"""
|
|
with _from_here():
|
|
binding = edtlib.Binding(
|
|
path=path,
|
|
fname2path=YAML_KNOWN_BASE_BINDINGS,
|
|
raw=None,
|
|
require_compatible=False,
|
|
require_description=False,
|
|
)
|
|
return binding
|
|
|
|
|
|
def child_binding_of(path: str) -> edtlib.Binding:
|
|
"""Load YAML file as Binding instance, and returns its child-binding.
|
|
The child-binding must exist.
|
|
|
|
Args:
|
|
path: Path relative to ZEPHYR_BASE/scripts/dts/python-devicetree/tests.
|
|
"""
|
|
binding = load_binding(path)
|
|
assert binding.child_binding
|
|
return binding.child_binding
|
|
|
|
|
|
def grandchild_binding_of(path: str) -> edtlib.Binding:
|
|
"""Load YAML file as Binding instance, and returns its grandchild-binding.
|
|
The grandchild-binding must exist.
|
|
|
|
Args:
|
|
path: Path relative to ZEPHYR_BASE/scripts/dts/python-devicetree/tests.
|
|
"""
|
|
child_binding = child_binding_of(path)
|
|
assert child_binding.child_binding
|
|
return child_binding.child_binding
|
|
|
|
|
|
def verify_expected_propspec(
|
|
propspec: edtlib.PropertySpec,
|
|
/,
|
|
*,
|
|
# Most properties are integers.
|
|
expect_type: str = "int",
|
|
expect_req: bool = False,
|
|
expect_desc: str | None = None,
|
|
expect_enum: list[int | str] | None = None,
|
|
expect_const: Any | None = None,
|
|
expect_default: Any | None = None,
|
|
) -> None:
|
|
"""Compare a property specification with the definitions
|
|
we (finally) expect.
|
|
|
|
All definitions are tested for equality.
|
|
|
|
Args:
|
|
propsec: The property specification to verify.
|
|
expect_type: The expected property type definition.
|
|
expect_req: Whether the property is expected to be required.
|
|
expect_desc: The expected property description.
|
|
expect_enum: The expected property "enum:" definition.
|
|
expect_const: The expected property "const:" definition.
|
|
expect_default: The expected property "default:" definition.
|
|
"""
|
|
assert expect_type == propspec.type
|
|
assert expect_req == propspec.required
|
|
assert expect_desc == propspec.description
|
|
assert expect_enum == propspec.enum
|
|
assert expect_const == propspec.const
|
|
assert expect_default == propspec.default
|
|
|
|
|
|
def verify_binding_propspecs_consistency(binding: edtlib.Binding) -> None:
|
|
"""Verify consistency between what's in Binding.prop2specs
|
|
and Binding.raw.
|
|
|
|
Asserts that:
|
|
Binding.raw["properties"][prop] == Binding.prop2specs[prop]._raw
|
|
|
|
If the binding has a child-binding, also recursively verify child-bindings.
|
|
|
|
NOTE: do not confuse with binding.prop2specs[prop].binding == binding,
|
|
which we do not assume here.
|
|
"""
|
|
if binding.prop2specs:
|
|
assert set(binding.raw["properties"].keys()) == set(binding.prop2specs.keys())
|
|
assert all(
|
|
binding.raw["properties"][prop] == propspec._raw
|
|
for prop, propspec in binding.prop2specs.items()
|
|
)
|
|
if binding.child_binding:
|
|
verify_binding_propspecs_consistency(binding.child_binding)
|
|
|
|
|
|
def test_expect_propspecs_inherited_bindings() -> None:
|
|
"""Test the basics of including property specifications.
|
|
|
|
Specifications are simply inherited without modifications
|
|
up to the grandchild-binding level.
|
|
|
|
Check that we actually inherit all expected definitions as-is.
|
|
"""
|
|
binding = load_binding("test-bindings-init/base_inherit.yaml")
|
|
|
|
# Binding level.
|
|
assert {
|
|
"prop-1",
|
|
"prop-2",
|
|
"prop-enum",
|
|
"prop-req",
|
|
"prop-const",
|
|
"prop-default",
|
|
} == set(binding.prop2specs.keys())
|
|
propspec = binding.prop2specs["prop-1"]
|
|
verify_expected_propspec(propspec, expect_desc="Base property 1.")
|
|
propspec = binding.prop2specs["prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = binding.prop2specs["prop-enum"]
|
|
verify_expected_propspec(propspec, expect_type="string", expect_enum=["FOO", "BAR"])
|
|
propspec = binding.prop2specs["prop-const"]
|
|
verify_expected_propspec(propspec, expect_const=8)
|
|
propspec = binding.prop2specs["prop-req"]
|
|
verify_expected_propspec(propspec, expect_req=True)
|
|
propspec = binding.prop2specs["prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=1)
|
|
|
|
# Child-Binding level.
|
|
assert binding.child_binding
|
|
child_binding = binding.child_binding
|
|
assert {
|
|
"child-prop-1",
|
|
"child-prop-2",
|
|
"child-prop-enum",
|
|
"child-prop-req",
|
|
"child-prop-const",
|
|
"child-prop-default",
|
|
} == set(child_binding.prop2specs.keys())
|
|
propspec = child_binding.prop2specs["child-prop-1"]
|
|
verify_expected_propspec(propspec, expect_desc="Base child-prop 1.")
|
|
propspec = child_binding.prop2specs["child-prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = child_binding.prop2specs["child-prop-enum"]
|
|
verify_expected_propspec(propspec, expect_type="string", expect_enum=["CHILD_FOO", "CHILD_BAR"])
|
|
propspec = child_binding.prop2specs["child-prop-const"]
|
|
verify_expected_propspec(propspec, expect_const=16)
|
|
propspec = child_binding.prop2specs["child-prop-req"]
|
|
verify_expected_propspec(propspec, expect_req=True)
|
|
propspec = child_binding.prop2specs["child-prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=2)
|
|
|
|
# GrandChild-Binding level.
|
|
assert child_binding.child_binding
|
|
grandchild_binding = child_binding.child_binding
|
|
assert {
|
|
"grandchild-prop-1",
|
|
"grandchild-prop-2",
|
|
"grandchild-prop-enum",
|
|
"grandchild-prop-req",
|
|
"grandchild-prop-const",
|
|
"grandchild-prop-default",
|
|
} == set(grandchild_binding.prop2specs.keys())
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-1"]
|
|
verify_expected_propspec(propspec, expect_desc="Base grandchild-prop 1.")
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["GRANDCHILD_FOO", "GRANDCHILD_BAR"],
|
|
)
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-const"]
|
|
verify_expected_propspec(propspec, expect_const=32)
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-req"]
|
|
verify_expected_propspec(propspec, expect_req=True)
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=3)
|
|
|
|
|
|
def test_expect_propspecs_amended_bindings() -> None:
|
|
"""Test the basics of including and amending property specifications.
|
|
|
|
Base specifications are included once at the binding level:
|
|
|
|
include: base.yaml
|
|
properties:
|
|
# Amend base.yaml
|
|
child-binding:
|
|
properties:
|
|
# Amend base.yaml
|
|
child-binding:
|
|
properties:
|
|
# Amend base.yaml
|
|
|
|
Check that we finally get the expected property specifications
|
|
up to the grandchild-binding level.
|
|
"""
|
|
binding = load_binding("test-bindings-init/base_amend.yaml")
|
|
|
|
# Binding level.
|
|
#
|
|
assert {
|
|
"prop-1",
|
|
"prop-2",
|
|
"prop-enum",
|
|
"prop-req",
|
|
"prop-const",
|
|
"prop-default",
|
|
"prop-new",
|
|
} == set(binding.prop2specs.keys())
|
|
propspec = binding.prop2specs["prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
# Amended in base_amend.yaml.
|
|
expect_desc="Overwritten description.",
|
|
expect_const=0xF0,
|
|
)
|
|
propspec = binding.prop2specs["prop-2"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
# Amended in base_amend.yaml.
|
|
expect_desc="New description.",
|
|
expect_enum=["EXT_FOO", "EXT_BAR"],
|
|
expect_default="EXT_FOO",
|
|
)
|
|
propspec = binding.prop2specs["prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["FOO", "BAR"],
|
|
# Amended in base_amend.yaml.
|
|
expect_req=True,
|
|
)
|
|
# Inherited from base.yaml without modification.
|
|
propspec = binding.prop2specs["prop-const"]
|
|
verify_expected_propspec(propspec, expect_const=8)
|
|
propspec = binding.prop2specs["prop-req"]
|
|
verify_expected_propspec(propspec, expect_req=True)
|
|
propspec = binding.prop2specs["prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=1)
|
|
|
|
# New property in base_amend.yaml.
|
|
propspec = binding.prop2specs["prop-new"]
|
|
verify_expected_propspec(propspec)
|
|
|
|
# Child-Binding level.
|
|
#
|
|
assert binding.child_binding
|
|
child_binding = binding.child_binding
|
|
assert {
|
|
"child-prop-1",
|
|
"child-prop-2",
|
|
"child-prop-enum",
|
|
"child-prop-req",
|
|
"child-prop-const",
|
|
"child-prop-default",
|
|
"child-prop-new",
|
|
} == set(child_binding.prop2specs.keys())
|
|
propspec = child_binding.prop2specs["child-prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
# Amended in base_amend.yaml.
|
|
expect_desc="Overwritten description (child).",
|
|
expect_const=0xF1,
|
|
)
|
|
propspec = child_binding.prop2specs["child-prop-2"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
# Amended in base_amend.yaml.
|
|
expect_desc="New description (child).",
|
|
expect_enum=["CHILD_EXT_FOO", "CHILD_EXT_BAR"],
|
|
expect_default="CHILD_EXT_FOO",
|
|
)
|
|
propspec = child_binding.prop2specs["child-prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["CHILD_FOO", "CHILD_BAR"],
|
|
# Amended in base_amend.yaml.
|
|
expect_req=True,
|
|
)
|
|
# Inherited from base.yaml without modification.
|
|
propspec = child_binding.prop2specs["child-prop-const"]
|
|
verify_expected_propspec(propspec, expect_const=16)
|
|
propspec = child_binding.prop2specs["child-prop-req"]
|
|
verify_expected_propspec(propspec, expect_req=True)
|
|
propspec = child_binding.prop2specs["child-prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=2)
|
|
|
|
# New property in base_amend.yaml.
|
|
propspec = child_binding.prop2specs["child-prop-new"]
|
|
verify_expected_propspec(propspec)
|
|
|
|
# GrandChild-Binding level.
|
|
#
|
|
assert child_binding.child_binding
|
|
grandchild_binding = child_binding.child_binding
|
|
assert {
|
|
"grandchild-prop-1",
|
|
"grandchild-prop-2",
|
|
"grandchild-prop-enum",
|
|
"grandchild-prop-req",
|
|
"grandchild-prop-const",
|
|
"grandchild-prop-default",
|
|
"grandchild-prop-new",
|
|
} == set(grandchild_binding.prop2specs.keys())
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
# Amended in base_amend.yaml.
|
|
expect_desc="Overwritten description (grandchild).",
|
|
expect_const=0xF2,
|
|
)
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-2"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
# Amended in base_amend.yaml.
|
|
expect_desc="New description (grandchild).",
|
|
expect_enum=["GRANDCHILD_EXT_FOO", "GRANDCHILD_EXT_BAR"],
|
|
expect_default="GRANDCHILD_EXT_FOO",
|
|
)
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["GRANDCHILD_FOO", "GRANDCHILD_BAR"],
|
|
# Amended in base_amend.yaml.
|
|
expect_req=True,
|
|
)
|
|
# Inherited from base.yaml without modification.
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-const"]
|
|
verify_expected_propspec(propspec, expect_const=32)
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-req"]
|
|
verify_expected_propspec(propspec, expect_req=True)
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=3)
|
|
|
|
# New property in base_amend.yaml.
|
|
propspec = grandchild_binding.prop2specs["grandchild-prop-new"]
|
|
verify_expected_propspec(propspec)
|
|
|
|
|
|
def test_expect_propspecs_multi_child_binding() -> None:
|
|
"""Test including base bindings at multiple levels.
|
|
|
|
Base specifications are included at the binding, child-binding
|
|
and child-binding levels:
|
|
|
|
include: base.yaml
|
|
child-binding:
|
|
include: base.yaml
|
|
child-binding:
|
|
include: base.yaml
|
|
|
|
This test checks that we finally get the expected property specifications
|
|
at the child-binding level.
|
|
"""
|
|
binding = child_binding_of("test-bindings-init/base_multi.yaml")
|
|
|
|
assert {
|
|
# From top-level "include:" element.
|
|
"child-prop-1",
|
|
"child-prop-2",
|
|
"child-prop-enum",
|
|
# From "child-binding: include:" element.
|
|
"prop-1",
|
|
"prop-2",
|
|
"prop-enum",
|
|
} == set(binding.prop2specs.keys())
|
|
|
|
# Inherited from base.yaml without modification.
|
|
propspec = binding.prop2specs["child-prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = binding.prop2specs["child-prop-enum"]
|
|
verify_expected_propspec(propspec, expect_type="string", expect_enum=["CHILD_FOO", "CHILD_BAR"])
|
|
|
|
propspec = binding.prop2specs["child-prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_desc="Base child-prop 1.",
|
|
# Amended in base_multi.yaml.
|
|
expect_const=0xF1,
|
|
)
|
|
propspec = binding.prop2specs["prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_desc="Base property 1.",
|
|
# Amended in base_multi.yaml.
|
|
expect_const=0xF1,
|
|
)
|
|
propspec = binding.prop2specs["prop-2"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
# Amended in base_multi.yaml.
|
|
expect_desc="New description (child).",
|
|
)
|
|
propspec = binding.prop2specs["prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["FOO", "BAR"],
|
|
# Amended in base_multi.yaml.
|
|
expect_default="FOO",
|
|
expect_req=True,
|
|
)
|
|
|
|
|
|
def test_expect_propspecs_multi_grandchild_binding() -> None:
|
|
"""Test including base bindings at multiple levels.
|
|
|
|
This test checks that we finally get the expected property specifications
|
|
at the grandchild-binding level.
|
|
|
|
See also: test_expect_propspecs_multi_child_binding()
|
|
"""
|
|
binding = grandchild_binding_of("test-bindings-init/base_multi.yaml")
|
|
|
|
assert {
|
|
# From top-level "include:" element.
|
|
"grandchild-prop-1",
|
|
"grandchild-prop-2",
|
|
"grandchild-prop-enum",
|
|
# From "child-binding: include:" element.
|
|
"child-prop-1",
|
|
"child-prop-2",
|
|
"child-prop-enum",
|
|
# From "child-binding: child-binding: include:" element.
|
|
"prop-1",
|
|
"prop-2",
|
|
"prop-enum",
|
|
} == set(binding.prop2specs.keys())
|
|
|
|
# Inherited from base.yaml without modification.
|
|
propspec = binding.prop2specs["grandchild-prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = binding.prop2specs["grandchild-prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["GRANDCHILD_FOO", "GRANDCHILD_BAR"],
|
|
)
|
|
propspec = binding.prop2specs["child-prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = binding.prop2specs["child-prop-enum"]
|
|
verify_expected_propspec(propspec, expect_type="string", expect_enum=["CHILD_FOO", "CHILD_BAR"])
|
|
|
|
propspec = binding.prop2specs["grandchild-prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_desc="Base grandchild-prop 1.",
|
|
# Amended in base_multi.yaml.
|
|
expect_const=0xF2,
|
|
)
|
|
propspec = binding.prop2specs["child-prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_desc="Base child-prop 1.",
|
|
# Amended in base_multi.yaml.
|
|
expect_const=0xF2,
|
|
)
|
|
propspec = binding.prop2specs["prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_desc="Base property 1.",
|
|
# Amended in base_amend.yaml.
|
|
expect_const=0xF2,
|
|
)
|
|
propspec = binding.prop2specs["prop-2"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
# Amended in base_amend.yaml.
|
|
expect_desc="New description (grandchild).",
|
|
)
|
|
propspec = binding.prop2specs["prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["FOO", "BAR"],
|
|
# Amended in base_amend.yaml.
|
|
expect_req=True,
|
|
expect_default="FOO",
|
|
)
|
|
|
|
|
|
def test_expect_propspecs_multi_grand_grandchild_binding() -> None:
|
|
"""Test including base bindings at multiple levels.
|
|
|
|
This test checks that we finally get the expected property specifications
|
|
at the grand-grandchild-binding level.
|
|
|
|
See also: test_expect_propspecs_multi_child_binding()
|
|
"""
|
|
binding = grandchild_binding_of("test-bindings-init/base_multi.yaml").child_binding
|
|
assert binding
|
|
|
|
assert {
|
|
# From "child-binding: include:" element.
|
|
"child-prop-1",
|
|
"child-prop-2",
|
|
"child-prop-enum",
|
|
# From "child-binding: child-binding: include:" element.
|
|
"grandchild-prop-1",
|
|
"grandchild-prop-2",
|
|
"grandchild-prop-enum",
|
|
} == set(binding.prop2specs.keys())
|
|
|
|
# Inherited from base.yaml without modification.
|
|
propspec = binding.prop2specs["child-prop-1"]
|
|
verify_expected_propspec(propspec, expect_desc="Base child-prop 1.")
|
|
propspec = binding.prop2specs["child-prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = binding.prop2specs["child-prop-enum"]
|
|
verify_expected_propspec(propspec, expect_type="string", expect_enum=["CHILD_FOO", "CHILD_BAR"])
|
|
propspec = binding.prop2specs["grandchild-prop-1"]
|
|
verify_expected_propspec(propspec, expect_desc="Base grandchild-prop 1.")
|
|
propspec = binding.prop2specs["grandchild-prop-2"]
|
|
verify_expected_propspec(propspec, expect_type="string")
|
|
propspec = binding.prop2specs["grandchild-prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["GRANDCHILD_FOO", "GRANDCHILD_BAR"],
|
|
)
|
|
|
|
|
|
def test_expect_propspecs_diamond_binding() -> None:
|
|
"""Test property specifications produced by diamond inheritance.
|
|
|
|
This test checks that we finally get the expected property specifications
|
|
at the binding level.
|
|
"""
|
|
binding = load_binding("test-bindings-init/diamond.yaml")
|
|
|
|
assert {
|
|
# From base.yaml, amended in base_amend.yaml (left),
|
|
# last modified in thing.yaml (right).
|
|
"prop-1",
|
|
# From base.yaml, amended in base_amend.yaml (left),
|
|
# and thing.yaml (right), last modified in diamond.yaml(top).
|
|
"prop-enum",
|
|
# From base.yaml, inherited in base_amend.yaml (left).
|
|
"prop-default",
|
|
# From thing.yaml (right).
|
|
"prop-thing",
|
|
# From diamond.yaml (top).
|
|
"prop-diamond",
|
|
} == set(binding.prop2specs.keys())
|
|
|
|
# Inherited from base.yaml without modification.
|
|
propspec = binding.prop2specs["prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=1)
|
|
# Inherited from thing.yaml without modification.
|
|
propspec = binding.prop2specs["prop-thing"]
|
|
verify_expected_propspec(propspec, expect_desc="Thing property.")
|
|
|
|
# New property in diamond.yaml.
|
|
propspec = binding.prop2specs["prop-diamond"]
|
|
verify_expected_propspec(propspec)
|
|
|
|
propspec = binding.prop2specs["prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
# From base_amend.yaml.
|
|
expect_const=0xF0,
|
|
# Included first wins.
|
|
expect_desc="Overwritten description.",
|
|
# From thing.yaml.
|
|
expect_default=1,
|
|
)
|
|
propspec = binding.prop2specs["prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["FOO", "BAR"],
|
|
# From base_amend.yaml.
|
|
expect_req=True,
|
|
# From diamond.yaml.
|
|
expect_desc="Overwritten in diamond.yaml.",
|
|
expect_default="FOO",
|
|
)
|
|
|
|
|
|
def test_expect_propspecs_diamond_child_binding() -> None:
|
|
"""Test property specifications produced by diamond inheritance.
|
|
|
|
This test checks that we finally get the expected property specifications
|
|
at the child-binding level.
|
|
"""
|
|
binding = child_binding_of("test-bindings-init/diamond.yaml")
|
|
|
|
assert {
|
|
# From base.yaml, amended in base_amend.yaml (left),
|
|
# last modified in thing.yaml (right).
|
|
"child-prop-1",
|
|
# From base.yaml, amended in base_amend.yaml (left),
|
|
# and thing.yaml (right), last modified in diamond.yaml(top).
|
|
"child-prop-enum",
|
|
# From base.yaml, inherited in base_amend.yaml (left).
|
|
"child-prop-default",
|
|
# From thing.yaml (right).
|
|
"child-prop-thing",
|
|
# From diamond.yaml (top).
|
|
"child-prop-diamond",
|
|
} == set(binding.prop2specs.keys())
|
|
|
|
propspec = binding.prop2specs["child-prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
# From base_amend.yaml.
|
|
expect_const=0xF1,
|
|
# Included first wins.
|
|
expect_desc="Overwritten description (child).",
|
|
# From thing.yaml.
|
|
expect_default=2,
|
|
)
|
|
|
|
propspec = binding.prop2specs["child-prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["CHILD_FOO", "CHILD_BAR"],
|
|
# From base_amend.yaml.
|
|
# ORed with thing.yaml.
|
|
expect_req=True,
|
|
# From diamond.yaml.
|
|
expect_default="CHILD_FOO",
|
|
expect_desc="Overwritten in diamond.yaml (child).",
|
|
)
|
|
|
|
# Inherited from base.yaml without modification.
|
|
propspec = binding.prop2specs["child-prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=2)
|
|
# Inherited from thing.yaml without modification.
|
|
propspec = binding.prop2specs["child-prop-thing"]
|
|
verify_expected_propspec(propspec, expect_desc="Thing child-binding property.")
|
|
|
|
# New property in diamond.yaml.
|
|
propspec = binding.prop2specs["child-prop-diamond"]
|
|
verify_expected_propspec(propspec)
|
|
|
|
|
|
def test_expect_propspecs_diamond_grandchild_binding() -> None:
|
|
"""Test property specifications produced by diamond inheritance.
|
|
|
|
This test checks that we finally get the expected property specifications
|
|
at the grandchild-binding level.
|
|
"""
|
|
binding = grandchild_binding_of("test-bindings-init/diamond.yaml")
|
|
|
|
assert {
|
|
# From base.yaml, amended in base_amend.yaml (left),
|
|
# last modified in thing.yaml (right).
|
|
"grandchild-prop-1",
|
|
# From base.yaml, amended in base_amend.yaml (left),
|
|
# last modified in diamond.yaml (top).
|
|
"grandchild-prop-enum",
|
|
# From base.yaml, inherited in base_amend.yaml (left).
|
|
"grandchild-prop-default",
|
|
# From thing.yaml (right).
|
|
"grandchild-prop-thing",
|
|
# From diamond.yaml (top).
|
|
"grandchild-prop-diamond",
|
|
} == set(binding.prop2specs.keys())
|
|
|
|
propspec = binding.prop2specs["grandchild-prop-1"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
# From base_amend.yaml.
|
|
expect_const=0xF2,
|
|
# Included first wins.
|
|
expect_desc="Overwritten description (grandchild).",
|
|
# From thing.yaml.
|
|
expect_default=3,
|
|
)
|
|
|
|
propspec = binding.prop2specs["grandchild-prop-enum"]
|
|
verify_expected_propspec(
|
|
propspec,
|
|
expect_type="string",
|
|
expect_enum=["GRANDCHILD_FOO", "GRANDCHILD_BAR"],
|
|
# From base_amend.yaml.
|
|
# ORed with thing.yaml.
|
|
expect_req=True,
|
|
# From diamond.yaml.
|
|
expect_default="GRANDCHILD_FOO",
|
|
expect_desc="Overwritten in diamond.yaml (grandchild).",
|
|
)
|
|
|
|
# Inherited from base.yaml without modification.
|
|
propspec = binding.prop2specs["grandchild-prop-default"]
|
|
verify_expected_propspec(propspec, expect_default=3)
|
|
# Inherited from thing.yaml without modification.
|
|
propspec = binding.prop2specs["grandchild-prop-thing"]
|
|
verify_expected_propspec(propspec, expect_desc="Thing grandchild-binding property.")
|
|
|
|
# New property in diamond.yaml.
|
|
propspec = binding.prop2specs["grandchild-prop-diamond"]
|
|
verify_expected_propspec(propspec)
|
|
|
|
|
|
def test_binding_description_overwrite() -> None:
|
|
"""Test whether we can overwrite a binding's description.
|
|
|
|
Included files can't overwrite the description set by the including binding
|
|
(despite that "description:" appears before "include:").
|
|
|
|
This seems consistent: the top-level binding file "wins".
|
|
"""
|
|
binding = load_binding("test-bindings-init/compat_desc.yaml")
|
|
assert binding.description == "Binding description."
|
|
|
|
binding = load_binding("test-bindings-init/compat_desc_multi.yaml")
|
|
assert binding.description == "Binding description (multi)."
|
|
|
|
|
|
def test_binding_compat_overwrite() -> None:
|
|
"""Test whether we can overwrite a binding's compatible string.
|
|
|
|
Included files can't overwrite the compatible string set by the
|
|
including binding (despite that "compatible:" appears before "include:").
|
|
|
|
This seems consistent: the top-level binding file "wins".
|
|
"""
|
|
binding = load_binding("test-bindings-init/compat_desc.yaml")
|
|
assert binding.compatible == "vnd,compat-desc"
|
|
|
|
binding = load_binding("test-bindings-init/compat_desc_multi.yaml")
|
|
assert binding.compatible == "vnd,compat-desc-multi"
|
|
|
|
|
|
def test_child_binding_description_overwrite() -> None:
|
|
"""Test whether we can overwrite a child-binding's description.
|
|
|
|
An including binding can overwrite an inherited child-binding's description.
|
|
|
|
When we include multiple files overwriting the description
|
|
at the child-binding level, the first "wins".
|
|
"""
|
|
child_binding = child_binding_of("test-bindings-init/compat_desc.yaml")
|
|
# Overwrite inherited description.
|
|
assert child_binding.description == "Child-binding description."
|
|
|
|
child_binding = child_binding_of("test-bindings-init/compat_desc_multi.yaml")
|
|
# When inherited multiple times, the first "description:" wins.
|
|
assert child_binding.description == "Child-binding description (base)."
|
|
|
|
|
|
def test_child_binding_compat_overwrite() -> None:
|
|
"""Test whether we can overwrite a child-binding's compatible string.
|
|
|
|
An including binding can overwrite an inherited child-binding's
|
|
compatible string.
|
|
|
|
When we include multiple files overwriting the compatible string
|
|
at the child-binding level, the first "wins".
|
|
"""
|
|
child_binding = child_binding_of("test-bindings-init/compat_desc.yaml")
|
|
# Overwrite inherited description.
|
|
assert child_binding.compatible == "vnd,child-compat-desc"
|
|
|
|
child_binding = child_binding_of("test-bindings-init/compat_desc_multi.yaml")
|
|
# When inherited multiple times, the first "compatible:" wins.
|
|
assert child_binding.compatible == "vnd,child-compat-desc-base"
|
|
|
|
|
|
def test_grandchild_binding_description_overwrite() -> None:
|
|
"""Test whether we can overwrite a grandchild-binding's description.
|
|
|
|
See also: test_child_binding_description_overwrite()
|
|
"""
|
|
grandchild_binding = grandchild_binding_of("test-bindings-init/compat_desc.yaml")
|
|
assert grandchild_binding.description == "Grandchild-binding description."
|
|
|
|
grandchild_binding = grandchild_binding_of("test-bindings-init/compat_desc_multi.yaml")
|
|
assert grandchild_binding.description == "Grandchild-binding description (base)."
|
|
|
|
|
|
def test_grandchild_binding_compat_overwrite() -> None:
|
|
"""Test whether we can overwrite a grandchild-binding's compatible string.
|
|
|
|
See also: test_child_binding_compat_overwrite()
|
|
"""
|
|
grandchild_binding = grandchild_binding_of("test-bindings-init/compat_desc.yaml")
|
|
# Overwrite inherited description.
|
|
assert grandchild_binding.compatible == "vnd,grandchild-compat-desc"
|
|
|
|
grandchild_binding = grandchild_binding_of("test-bindings-init/compat_desc_multi.yaml")
|
|
# When inherited multiple times, the first "compatible:" wins.
|
|
assert grandchild_binding.compatible == "vnd,grandchild-compat-desc-base"
|
|
|
|
|
|
def test_filter_inherited_propspecs_basics() -> None:
|
|
"""Test the basics of filtering properties inherited via an intermediary
|
|
binding file.
|
|
|
|
Use-case "B filters I includes X":
|
|
- X is a base binding file, specifying common properties
|
|
- I is an intermediary binding file, which includes X without modification
|
|
nor filter
|
|
- B includes I, filtering the properties it chooses to inherit
|
|
with an allowlist or a blocklist
|
|
|
|
Checks, up to the grandchild-binding level, that the properties inherited
|
|
from X via I are actually filtered as B intends to.
|
|
"""
|
|
# Binding level.
|
|
binding = load_binding("test-bindings-init/simple_allowlist.yaml")
|
|
# Allowed properties.
|
|
assert {"prop-1", "prop-2"} == set(binding.prop2specs.keys())
|
|
binding = load_binding("test-bindings-init/simple_blocklist.yaml")
|
|
# Non blocked properties.
|
|
assert {"prop-2", "prop-3"} == set(binding.prop2specs.keys())
|
|
|
|
# Child-binding level.
|
|
child_binding = child_binding_of("test-bindings-init/simple_allowlist.yaml")
|
|
# Allowed properties.
|
|
assert {"child-prop-1", "child-prop-2"} == set(child_binding.prop2specs.keys())
|
|
child_binding = child_binding_of("test-bindings-init/simple_blocklist.yaml")
|
|
# Non blocked properties.
|
|
assert {"child-prop-2", "child-prop-3"} == set(child_binding.prop2specs.keys())
|
|
|
|
# GrandChild-binding level.
|
|
grandchild_binding = grandchild_binding_of("test-bindings-init/simple_allowlist.yaml")
|
|
# Allowed properties.
|
|
assert {"grandchild-prop-1", "grandchild-prop-2"} == set(grandchild_binding.prop2specs.keys())
|
|
grandchild_binding = grandchild_binding_of("test-bindings-init/simple_blocklist.yaml")
|
|
# Non blocked properties.
|
|
assert {"grandchild-prop-2", "grandchild-prop-3"} == set(grandchild_binding.prop2specs.keys())
|
|
|
|
|
|
def test_filter_inherited_propspecs_among_allowed() -> None:
|
|
"""Test filtering properties which have been allowed by an intermediary
|
|
binding file.
|
|
|
|
Complementary to test_filter_inherited_propspecs_basics().
|
|
|
|
Use-case "B filters I filters X":
|
|
- X is a base binding file, specifying common properties
|
|
- I is an intermediary binding file, filtering the properties specified
|
|
in X with an allowlist
|
|
- B includes I, filtering the properties it chooses to inherit
|
|
also with an allowlist
|
|
|
|
Checks, up to the grandchild-binding level, that B inherits the properties
|
|
specified in X which are first allowed in I, then also allowed in B.
|
|
|
|
For that, we check that if B allows only properties that are not allowed in I,
|
|
we then end up with no property at all.
|
|
"""
|
|
binding = load_binding("test-bindings-init/filter_among_allowed.yaml")
|
|
assert not set(binding.prop2specs.keys())
|
|
assert binding.child_binding
|
|
child_binding = binding.child_binding
|
|
assert not set(child_binding.prop2specs.keys())
|
|
assert child_binding.child_binding
|
|
grandchild_binding = child_binding.child_binding
|
|
assert not set(grandchild_binding.prop2specs.keys())
|
|
|
|
|
|
def test_filter_inherited_propspecs_among_notblocked() -> None:
|
|
"""Test filtering properties which have not been blocked by an intermediary
|
|
binding file.
|
|
|
|
Complementary to test_filter_inherited_propspecs_basics().
|
|
|
|
Use-case "B filters I filters X":
|
|
- X is a base binding file, specifying common properties
|
|
- I is an intermediary binding file, filtering the properties specified
|
|
in X with a blocklist
|
|
- B includes I, filtering the properties it chooses to inherit
|
|
also with a blocklist
|
|
|
|
Checks, up to the grandchild-binding level, that B inherits the properties
|
|
specified in X which are not blocked in I, then neither blocked in B.
|
|
|
|
For that, we check that if B blocks all properties that are not blocked in I,
|
|
we then end up with no property at all.
|
|
"""
|
|
binding = load_binding("test-bindings-init/filter_among_notblocked.yaml")
|
|
assert not set(binding.prop2specs.keys())
|
|
assert binding.child_binding
|
|
child_binding = binding.child_binding
|
|
assert not set(child_binding.prop2specs.keys())
|
|
assert child_binding.child_binding
|
|
grandchild_binding = child_binding.child_binding
|
|
assert not set(grandchild_binding.prop2specs.keys())
|
|
|
|
|
|
def test_filter_inherited_propspecs_allows_notblocked() -> None:
|
|
"""Test allowing properties which have not been blocked by an intermediary
|
|
binding file.
|
|
|
|
Complementary to test_filter_inherited_propspecs_basics().
|
|
|
|
Use-case "B filters I filters X":
|
|
- X is a base binding file, specifying common properties
|
|
- I is an intermediary binding file, filtering the properties specified
|
|
in X with a blocklist
|
|
- B includes I, filtering the properties it chooses to inherit
|
|
also with an allowlist
|
|
|
|
Checks, up to the grandchild-binding level, that B inherits the properties
|
|
specified in X which are not blocked in I, then allowed in B.
|
|
|
|
Permits to verify we can apply both "property-allowlist"
|
|
and "property-blocklist" filters to the same file,
|
|
as long as they're not applied simultaneously
|
|
(i.e. within the same YAML "include:" map).
|
|
"""
|
|
binding = load_binding("test-bindings-init/filter_allows_notblocked.yaml")
|
|
assert {"prop-2"} == set(binding.prop2specs.keys())
|
|
assert binding.child_binding
|
|
child_binding = binding.child_binding
|
|
assert {"child-prop-2"} == set(child_binding.prop2specs.keys())
|
|
assert child_binding.child_binding
|
|
grandchild_binding = child_binding.child_binding
|
|
assert {"grandchild-prop-2"} == set(grandchild_binding.prop2specs.keys())
|
|
|
|
|
|
def test_invalid_binding_type_override() -> None:
|
|
"""An including binding should not try to override the "type:"
|
|
of an inherited property.
|
|
|
|
Tested up to the grandchild-binding level.
|
|
"""
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_proptype.yaml")
|
|
assert "prop-1" in str(e)
|
|
assert "'int' replaced with 'string'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_child_proptype.yaml")
|
|
assert "child-prop-1" in str(e)
|
|
assert "'int' replaced with 'string'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_grandchild_proptype.yaml")
|
|
assert "grandchild-prop-1" in str(e)
|
|
assert "'int' replaced with 'string'" in str(e)
|
|
|
|
|
|
def test_invalid_binding_const_override() -> None:
|
|
"""An including binding should not try to override the "const:" value
|
|
in a property specification inherited from an included file.
|
|
|
|
Tested up to the grandchild-binding level.
|
|
"""
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_propconst.yaml")
|
|
assert "prop-const" in str(e)
|
|
assert "'8' replaced with '999'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_child_propconst.yaml")
|
|
assert "child-prop-const" in str(e)
|
|
assert "'16' replaced with '999'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_grandchild_propconst.yaml")
|
|
assert "grandchild-prop-const" in str(e)
|
|
assert "'32' replaced with '999'" in str(e)
|
|
|
|
|
|
def test_invalid_binding_required_override() -> None:
|
|
"""An including binding should not try to override "required: true"
|
|
in a property specification inherited from an included file.
|
|
|
|
Tested up to the grandchild-binding level.
|
|
"""
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_propreq.yaml")
|
|
assert "prop-req" in str(e)
|
|
assert "'True' replaced with 'False'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_child_propreq.yaml")
|
|
assert "child-prop-req" in str(e)
|
|
assert "'True' replaced with 'False'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_grandchild_propreq.yaml")
|
|
assert "grandchild-prop-req" in str(e)
|
|
assert "'True' replaced with 'False'" in str(e)
|
|
|
|
|
|
def test_invalid_binding_default_override() -> None:
|
|
"""An including binding should not try to override the "default:" value
|
|
in a property specification inherited from an included file.
|
|
|
|
Tested up to the grandchild-binding level.
|
|
"""
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_propdefault.yaml")
|
|
assert "prop-default" in str(e)
|
|
assert "'1' replaced with '999'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_child_propdefault.yaml")
|
|
assert "child-prop-default" in str(e)
|
|
assert "'2' replaced with '999'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_grandchild_propdefault.yaml")
|
|
assert "grandchild-prop-default" in str(e)
|
|
assert "'3' replaced with '999'" in str(e)
|
|
|
|
|
|
def test_invalid_binding_enum_override() -> None:
|
|
"""An including binding should not try to override the "enum:" values
|
|
in a property specification inherited from an included file.
|
|
|
|
Tested up to the grandchild-binding level.
|
|
"""
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_propenum.yaml")
|
|
assert "prop-enum" in str(e)
|
|
assert "'['FOO', 'BAR']' replaced with '['OTHER_FOO', 'OTHER_BAR']'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_child_propenum.yaml")
|
|
assert "child-prop-enum" in str(e)
|
|
assert "'['CHILD_FOO', 'CHILD_BAR']' replaced with '['OTHER_FOO', 'OTHER_BAR']'" in str(e)
|
|
|
|
with pytest.raises(edtlib.EDTError) as e:
|
|
load_binding("test-bindings-init/invalid_grandchild_propenum.yaml")
|
|
assert "grandchild-prop-enum" in str(e)
|
|
assert (
|
|
"'['GRANDCHILD_FOO', 'GRANDCHILD_BAR']' replaced with '['OTHER_FOO', 'OTHER_BAR']'"
|
|
in str(e)
|
|
)
|
|
|
|
|
|
def test_bindings_propspecs_consistency() -> None:
|
|
"""Verify property specifications consistency.
|
|
|
|
Consistency is recursively checked for all defined properties,
|
|
from top-level binding files down to their child bindings.
|
|
|
|
Consistency is checked with:
|
|
Binding.raw["properties"][prop] == Binding.prop2specs[prop]._raw
|
|
|
|
See verify_binding_propspecs_consistency().
|
|
"""
|
|
binding = load_binding("test-bindings-init/base_inherit.yaml")
|
|
verify_binding_propspecs_consistency(binding)
|
|
|
|
binding = load_binding("test-bindings-init/base_amend.yaml")
|
|
verify_binding_propspecs_consistency(binding)
|
|
|
|
binding = load_binding("test-bindings-init/base_multi.yaml")
|
|
verify_binding_propspecs_consistency(binding)
|
|
|
|
binding = load_binding("test-bindings-init/thing.yaml")
|
|
verify_binding_propspecs_consistency(binding)
|
|
|
|
binding = load_binding("test-bindings-init/diamond.yaml")
|
|
verify_binding_propspecs_consistency(binding)
|
|
|
|
|
|
# Borrowed from test_edtlib.py.
|
|
@contextlib.contextmanager
|
|
def _from_here() -> Generator[None, None, None]:
|
|
cwd = os.getcwd()
|
|
try:
|
|
os.chdir(os.path.dirname(__file__))
|
|
yield
|
|
finally:
|
|
os.chdir(cwd)
|
|
|
|
|
|
def _basename(path: str | None) -> str:
|
|
return os.path.basename(path or "?")
|