Synchronize with zephyr commit 018f59e46f

Snapshot to a recent zephyr main.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Martí Bolívar 2022-04-03 16:21:28 -07:00
parent e4213e9689
commit 9b6d3893ad
26 changed files with 1962 additions and 1055 deletions

View file

@ -1,2 +1,4 @@
__all__ = ['edtlib', 'dtlib']
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
__all__ = ['edtlib', 'dtlib']

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
This directory contains bindings used to test the 'include:' feature.

View file

@ -0,0 +1,11 @@
# SPDX-License-Identifier: BSD-3-Clause
description: |
An include must not give both an allowlist and a blocklist in a
child binding. This binding should cause an error.
compatible: allow-and-blocklist-child
include:
- name: include.yaml
child-binding:
property-blocklist: [x]
property-allowlist: [y]

View file

@ -0,0 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause
description: |
An include must not give both an allowlist and a blocklist.
This binding should cause an error.
compatible: allow-and-blocklist
include:
- name: include.yaml
property-blocklist: [x]
property-allowlist: [y]

View file

@ -0,0 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause
description: |
A property-allowlist, if given, must be a list. This binding should
cause an error.
compatible: allow-not-list
include:
- name: include.yaml
property-allowlist:
foo:

View file

@ -0,0 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
description: Valid property-allowlist.
compatible: allowlist
include:
- name: include.yaml
property-allowlist: [x]

View file

@ -0,0 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause
description: |
A property-blocklist, if given, must be a list. This binding should
cause an error.
compatible: block-not-list
include:
- name: include.yaml
property-blocklist:
foo:

View file

@ -0,0 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
description: Valid property-blocklist.
compatible: blocklist
include:
- name: include.yaml
property-blocklist: [x]

View file

@ -0,0 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
description: An empty property-allowlist is valid.
compatible: empty-allowlist
include:
- name: include.yaml
property-allowlist: []

View file

@ -0,0 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
description: An empty property-blocklist is valid.
compatible: empty-blocklist
include:
- name: include.yaml
property-blocklist: []

View file

@ -0,0 +1,11 @@
description: Test binding for filtering 'child-binding' properties
include:
- name: include.yaml
property-allowlist: [x]
child-binding:
property-blocklist: [child-prop-1]
child-binding:
property-allowlist: [grandchild-prop-1]
compatible: filter-child-bindings

View file

@ -0,0 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
description: Second file for testing "intermixed" includes.
compatible: include-2
properties:
a:
type: int

View file

@ -0,0 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause
description: |
Invalid include element: invalid keys are present.
compatible: include-invalid-keys
include:
- name: include.yaml
property-allowlist: [x]
bad-key-1: 3
bad-key-2: 3

View file

@ -0,0 +1,5 @@
description: |
Invalid include: wrong top level type.
compatible: include-invalid-type
include:
a-map-is-not-allowed-here: 3

View file

@ -0,0 +1,6 @@
# SPDX-License-Identifier: BSD-3-Clause
description: A map element with just a name is valid, and has no filters.
compatible: include-no-list
include:
- name: include.yaml

View file

@ -0,0 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
description: |
Invalid include element: no name key is present.
compatible: include-no-name
include:
- property-allowlist: [x]

View file

@ -0,0 +1,24 @@
# SPDX-License-Identifier: BSD-3-Clause
description: Test file for including other bindings
compatible: include
properties:
x:
type: int
y:
type: int
z:
type: int
child-binding:
properties:
child-prop-1:
type: int
child-prop-2:
type: int
child-binding:
properties:
grandchild-prop-1:
type: int
grandchild-prop-2:
type: int

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: BSD-3-Clause
description: Including intermixed file names and maps is valid.
compatible: intermixed
include:
- name: include.yaml
property-allowlist: [x]
- include-2.yaml

View file

@ -0,0 +1,9 @@
# SPDX-License-Identifier: BSD-3-Clause
description: Device.wrong_phandle_array_name test
compatible: "wrong_phandle_array_name"
properties:
wrong-phandle-array-name:
type: phandle-array

View file

@ -0,0 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause
description: Device.wrong_specifier_space_type test
compatible: "wrong_specifier_space_type"
properties:
wrong-type-for-specifier-space:
type: phandle
specifier-space: foobar

View file

@ -123,6 +123,110 @@
};
};
//
// 'ranges'
//
ranges-zero-cells {
#address-cells = <0>;
node {
#address-cells = <0>;
#size-cells = <0>;
ranges;
};
};
ranges-zero-parent-cells {
#address-cells = <0>;
node {
#address-cells = <1>;
#size-cells = <0>;
ranges = <0xA>,
<0x1A>,
<0x2A>;
};
};
ranges-one-address-cells {
#address-cells = <0>;
node {
reg = <1>;
#address-cells = <1>;
ranges = <0xA 0xB>,
<0x1A 0x1B>,
<0x2A 0x2B>;
};
};
ranges-one-address-two-size-cells {
#address-cells = <0>;
node {
reg = <1>;
#address-cells = <1>;
#size-cells = <2>;
ranges = <0xA 0xB 0xC>,
<0x1A 0x1B 0x1C>,
<0x2A 0x2B 0x2C>;
};
};
ranges-two-address-cells {
#address-cells = <1>;
node@1 {
reg = <1 2>;
ranges = <0xA 0xB 0xC 0xD>,
<0x1A 0x1B 0x1C 0x1D>,
<0x2A 0x2B 0x2C 0x2D>;
};
};
ranges-two-address-two-size-cells {
#address-cells = <1>;
node@1 {
reg = <1 2>;
#size-cells = <2>;
ranges = <0xA 0xB 0xC 0xD 0xE>,
<0x1A 0x1B 0x1C 0x1D 0x1E>,
<0x2A 0x2B 0x2C 0x2D 0x1D>;
};
};
ranges-three-address-cells {
node@1 {
reg = <0 1 2>;
#address-cells = <3>;
ranges = <0xA 0xB 0xC 0xD 0xE 0xF>,
<0x1A 0x1B 0x1C 0x1D 0x1E 0x1F>,
<0x2A 0x2B 0x2C 0x2D 0x2E 0x2F>;
};
};
ranges-three-address-two-size-cells {
node@1 {
reg = <0 1 2>;
#address-cells = <3>;
#size-cells = <2>;
ranges = <0xA 0xB 0xC 0xD 0xE 0xF 0x10>,
<0x1A 0x1B 0x1C 0x1D 0x1E 0x1F 0x110>,
<0x2A 0x2B 0x2C 0x2D 0x2E 0x2F 0x210>;
};
};
//
// 'reg'
//
@ -206,7 +310,7 @@
};
//
// For testing Node.parent and Node.children
// For testing hierarchy.
//
parent {

View file

@ -14,7 +14,7 @@ from devicetree import dtlib
#
# Run it using pytest (https://docs.pytest.org/en/stable/usage.html):
#
# $ pytest testdtlib.py
# $ pytest tests/test_dtlib.py
#
# Extra options you can pass to pytest for debugging:
#
@ -24,13 +24,15 @@ from devicetree import dtlib
# - to run a particular test function or functions, use
# '-k test_function_pattern_goes_here'
def parse(dts, include_path=()):
'''Parse a DTS string 'dts', using the given include path.'''
def parse(dts, include_path=(), **kwargs):
'''Parse a DTS string 'dts', using the given include path.
Any kwargs are passed on to DT().'''
fd, path = tempfile.mkstemp(prefix='pytest-', suffix='.dts')
try:
os.write(fd, dts.encode('utf-8'))
return dtlib.DT(path, include_path)
return dtlib.DT(path, include_path, **kwargs)
finally:
os.close(fd)
os.unlink(path)
@ -98,6 +100,16 @@ def temporary_chdir(dirname):
finally:
os.chdir(here)
def test_invalid_nodenames():
# Regression test that verifies node names are not matched against
# the more permissive set of rules used for property names.
verify_error_endswith("""
/dts-v1/;
/ { node? {}; };
""",
"/node?: bad character '?' in node name")
def test_cell_parsing():
'''Miscellaneous properties containing zero or more cells'''
@ -1538,30 +1550,30 @@ def test_prop_type():
};
""")
verify_type("empty", dtlib.TYPE_EMPTY)
verify_type("bytes1", dtlib.TYPE_BYTES)
verify_type("bytes2", dtlib.TYPE_BYTES)
verify_type("bytes3", dtlib.TYPE_BYTES)
verify_type("bytes4", dtlib.TYPE_BYTES)
verify_type("bytes5", dtlib.TYPE_BYTES)
verify_type("num", dtlib.TYPE_NUM)
verify_type("nums1", dtlib.TYPE_NUMS)
verify_type("nums2", dtlib.TYPE_NUMS)
verify_type("nums3", dtlib.TYPE_NUMS)
verify_type("nums4", dtlib.TYPE_NUMS)
verify_type("string", dtlib.TYPE_STRING)
verify_type("strings", dtlib.TYPE_STRINGS)
verify_type("phandle1", dtlib.TYPE_PHANDLE)
verify_type("phandle2", dtlib.TYPE_PHANDLE)
verify_type("phandles1", dtlib.TYPE_PHANDLES)
verify_type("phandles2", dtlib.TYPE_PHANDLES)
verify_type("phandle-and-nums-1", dtlib.TYPE_PHANDLES_AND_NUMS)
verify_type("phandle-and-nums-2", dtlib.TYPE_PHANDLES_AND_NUMS)
verify_type("phandle-and-nums-3", dtlib.TYPE_PHANDLES_AND_NUMS)
verify_type("path1", dtlib.TYPE_PATH)
verify_type("path2", dtlib.TYPE_PATH)
verify_type("compound1", dtlib.TYPE_COMPOUND)
verify_type("compound2", dtlib.TYPE_COMPOUND)
verify_type("empty", dtlib.Type.EMPTY)
verify_type("bytes1", dtlib.Type.BYTES)
verify_type("bytes2", dtlib.Type.BYTES)
verify_type("bytes3", dtlib.Type.BYTES)
verify_type("bytes4", dtlib.Type.BYTES)
verify_type("bytes5", dtlib.Type.BYTES)
verify_type("num", dtlib.Type.NUM)
verify_type("nums1", dtlib.Type.NUMS)
verify_type("nums2", dtlib.Type.NUMS)
verify_type("nums3", dtlib.Type.NUMS)
verify_type("nums4", dtlib.Type.NUMS)
verify_type("string", dtlib.Type.STRING)
verify_type("strings", dtlib.Type.STRINGS)
verify_type("phandle1", dtlib.Type.PHANDLE)
verify_type("phandle2", dtlib.Type.PHANDLE)
verify_type("phandles1", dtlib.Type.PHANDLES)
verify_type("phandles2", dtlib.Type.PHANDLES)
verify_type("phandle-and-nums-1", dtlib.Type.PHANDLES_AND_NUMS)
verify_type("phandle-and-nums-2", dtlib.Type.PHANDLES_AND_NUMS)
verify_type("phandle-and-nums-3", dtlib.Type.PHANDLES_AND_NUMS)
verify_type("path1", dtlib.Type.PATH)
verify_type("path2", dtlib.Type.PATH)
verify_type("compound1", dtlib.Type.COMPOUND)
verify_type("compound2", dtlib.Type.COMPOUND)
def test_prop_type_casting():
'''Test Property.to_{num,nums,string,strings,node}()'''
@ -2077,7 +2089,7 @@ foo: / {
def test_reprs():
'''Test the __repr__() functions.'''
dt = parse("""
dts = """
/dts-v1/;
/ {
@ -2086,28 +2098,31 @@ def test_reprs():
y = < 1 >;
};
};
""",
include_path=("foo", "bar"))
"""
assert re.fullmatch(r"DT\(filename='.*', include_path=\('foo', 'bar'\)\)",
dt = parse(dts, include_path=("foo", "bar"))
assert re.fullmatch(r"DT\(filename='.*', include_path=.'foo', 'bar'.\)",
repr(dt))
assert re.fullmatch("<Property 'x' at '/' in '.*'>",
repr(dt.root.props["x"]))
assert re.fullmatch("<Node /sub in '.*'>",
repr(dt.root.nodes["sub"]))
dt = parse(dts, include_path=iter(("foo", "bar")))
assert re.fullmatch(r"DT\(filename='.*', include_path=.'foo', 'bar'.\)",
repr(dt))
def test_names():
'''Tests for node/property names.'''
# The C tools disallow '@' in property names, but otherwise accept the same
# characters in node and property names. Emulate that instead of the DT spec
# (v0.2), which gives different characters for nodes and properties.
verify_parse(r"""
/dts-v1/;
/ {
// A leading \ is accepted but ignored in node/propert names
\aA0,._+*#?- = &_, &{/aA0,._+*#?@-};
\aA0,._+*#?- = &_, &{/aA0,._+@-};
// Names that overlap with operators and integer literals
@ -2118,7 +2133,8 @@ def test_names():
0 = [ 04 ];
0x123 = [ 05 ];
_: \aA0,._+*#?@- {
// Node names are more restrictive than property names.
_: \aA0,._+@- {
};
0 {
@ -2129,14 +2145,14 @@ def test_names():
/dts-v1/;
/ {
aA0,._+*#?- = &_, &{/aA0,._+*#?@-};
aA0,._+*#?- = &_, &{/aA0,._+@-};
+ = [ 00 ];
* = [ 02 ];
- = [ 01 ];
? = [ 03 ];
0 = [ 04 ];
0x123 = [ 05 ];
_: aA0,._+*#?@- {
_: aA0,._+@- {
};
0 {
};
@ -2244,3 +2260,13 @@ l1: l2: &foo {
/ {
};
""")
def test_dangling_alias():
dt = parse('''
/dts-v1/;
/ {
aliases { foo = "/missing"; };
};
''', force=True)
assert dt.get_node('/aliases').props['foo'].to_string() == '/missing'

View file

@ -78,6 +78,43 @@ def test_interrupts():
assert str(edt.get_node("/interrupt-map-bitops-test/node@70000000E").interrupts) == \
f"[<ControllerAndData, controller: <Node /interrupt-map-bitops-test/controller in 'test.dts', binding {filenames[2]}>, data: OrderedDict([('one', 3), ('two', 2)])>]"
def test_ranges():
'''Tests for the ranges property'''
with from_here():
edt = edtlib.EDT("test.dts", ["test-bindings"])
assert str(edt.get_node("/reg-ranges/parent").ranges) == \
"[<Range, child-bus-cells: 0x1, child-bus-addr: 0x1, parent-bus-cells: 0x2, parent-bus-addr: 0xa0000000b, length-cells 0x1, length 0x1>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x2, parent-bus-cells: 0x2, parent-bus-addr: 0xc0000000d, length-cells 0x1, length 0x2>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x4, parent-bus-cells: 0x2, parent-bus-addr: 0xe0000000f, length-cells 0x1, length 0x1>]"
assert str(edt.get_node("/reg-nested-ranges/grandparent").ranges) == \
"[<Range, child-bus-cells: 0x2, child-bus-addr: 0x0, parent-bus-cells: 0x3, parent-bus-addr: 0x30000000000000000, length-cells 0x2, length 0x200000002>]"
assert str(edt.get_node("/reg-nested-ranges/grandparent/parent").ranges) == \
"[<Range, child-bus-cells: 0x1, child-bus-addr: 0x0, parent-bus-cells: 0x2, parent-bus-addr: 0x200000000, length-cells 0x1, length 0x2>]"
assert str(edt.get_node("/ranges-zero-cells/node").ranges) == "[]"
assert str(edt.get_node("/ranges-zero-parent-cells/node").ranges) == \
"[<Range, child-bus-cells: 0x1, child-bus-addr: 0xa, parent-bus-cells: 0x0, length-cells 0x0>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x1a, parent-bus-cells: 0x0, length-cells 0x0>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x2a, parent-bus-cells: 0x0, length-cells 0x0>]"
assert str(edt.get_node("/ranges-one-address-cells/node").ranges) == \
"[<Range, child-bus-cells: 0x1, child-bus-addr: 0xa, parent-bus-cells: 0x0, length-cells 0x1, length 0xb>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x1a, parent-bus-cells: 0x0, length-cells 0x1, length 0x1b>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x2a, parent-bus-cells: 0x0, length-cells 0x1, length 0x2b>]"
assert str(edt.get_node("/ranges-one-address-two-size-cells/node").ranges) == \
"[<Range, child-bus-cells: 0x1, child-bus-addr: 0xa, parent-bus-cells: 0x0, length-cells 0x2, length 0xb0000000c>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x1a, parent-bus-cells: 0x0, length-cells 0x2, length 0x1b0000001c>, <Range, child-bus-cells: 0x1, child-bus-addr: 0x2a, parent-bus-cells: 0x0, length-cells 0x2, length 0x2b0000002c>]"
assert str(edt.get_node("/ranges-two-address-cells/node@1").ranges) == \
"[<Range, child-bus-cells: 0x2, child-bus-addr: 0xa0000000b, parent-bus-cells: 0x1, parent-bus-addr: 0xc, length-cells 0x1, length 0xd>, <Range, child-bus-cells: 0x2, child-bus-addr: 0x1a0000001b, parent-bus-cells: 0x1, parent-bus-addr: 0x1c, length-cells 0x1, length 0x1d>, <Range, child-bus-cells: 0x2, child-bus-addr: 0x2a0000002b, parent-bus-cells: 0x1, parent-bus-addr: 0x2c, length-cells 0x1, length 0x2d>]"
assert str(edt.get_node("/ranges-two-address-two-size-cells/node@1").ranges) == \
"[<Range, child-bus-cells: 0x2, child-bus-addr: 0xa0000000b, parent-bus-cells: 0x1, parent-bus-addr: 0xc, length-cells 0x2, length 0xd0000000e>, <Range, child-bus-cells: 0x2, child-bus-addr: 0x1a0000001b, parent-bus-cells: 0x1, parent-bus-addr: 0x1c, length-cells 0x2, length 0x1d0000001e>, <Range, child-bus-cells: 0x2, child-bus-addr: 0x2a0000002b, parent-bus-cells: 0x1, parent-bus-addr: 0x2c, length-cells 0x2, length 0x2d0000001d>]"
assert str(edt.get_node("/ranges-three-address-cells/node@1").ranges) == \
"[<Range, child-bus-cells: 0x3, child-bus-addr: 0xa0000000b0000000c, parent-bus-cells: 0x2, parent-bus-addr: 0xd0000000e, length-cells 0x1, length 0xf>, <Range, child-bus-cells: 0x3, child-bus-addr: 0x1a0000001b0000001c, parent-bus-cells: 0x2, parent-bus-addr: 0x1d0000001e, length-cells 0x1, length 0x1f>, <Range, child-bus-cells: 0x3, child-bus-addr: 0x2a0000002b0000002c, parent-bus-cells: 0x2, parent-bus-addr: 0x2d0000002e, length-cells 0x1, length 0x2f>]"
assert str(edt.get_node("/ranges-three-address-two-size-cells/node@1").ranges) == \
"[<Range, child-bus-cells: 0x3, child-bus-addr: 0xa0000000b0000000c, parent-bus-cells: 0x2, parent-bus-addr: 0xd0000000e, length-cells 0x2, length 0xf00000010>, <Range, child-bus-cells: 0x3, child-bus-addr: 0x1a0000001b0000001c, parent-bus-cells: 0x2, parent-bus-addr: 0x1d0000001e, length-cells 0x2, length 0x1f00000110>, <Range, child-bus-cells: 0x3, child-bus-addr: 0x2a0000002b0000002c, parent-bus-cells: 0x2, parent-bus-addr: 0x2d0000002e, length-cells 0x2, length 0x2f00000210>]"
def test_reg():
'''Tests for the regs property'''
with from_here():
@ -121,6 +158,20 @@ def test_hierarchy():
assert edt.get_node("/parent/child-1").children == {}
def test_child_index():
'''Test Node.child_index.'''
with from_here():
edt = edtlib.EDT("test.dts", ["test-bindings"])
parent, child_1, child_2 = [edt.get_node(path) for path in
("/parent",
"/parent/child-1",
"/parent/child-2")]
assert parent.child_index(child_1) == 0
assert parent.child_index(child_2) == 1
with pytest.raises(KeyError):
parent.child_index(parent)
def test_include():
'''Test 'include:' and the legacy 'inherits: !include ...' in bindings'''
with from_here():
@ -132,6 +183,91 @@ def test_include():
assert str(edt.get_node("/binding-include").props) == \
"OrderedDict([('foo', <Property, name: foo, type: int, value: 0>), ('bar', <Property, name: bar, type: int, value: 1>), ('baz', <Property, name: baz, type: int, value: 2>), ('qaz', <Property, name: qaz, type: int, value: 3>)])"
def test_include_filters():
'''Test property-allowlist and property-blocklist in an include.'''
fname2path = {'include.yaml': 'test-bindings-include/include.yaml',
'include-2.yaml': 'test-bindings-include/include-2.yaml'}
with pytest.raises(edtlib.EDTError) as e:
with from_here():
edtlib.Binding("test-bindings-include/allow-and-blocklist.yaml", fname2path)
assert ("should not specify both 'property-allowlist:' and 'property-blocklist:'"
in str(e.value))
with pytest.raises(edtlib.EDTError) as e:
with from_here():
edtlib.Binding("test-bindings-include/allow-and-blocklist-child.yaml", fname2path)
assert ("should not specify both 'property-allowlist:' and 'property-blocklist:'"
in str(e.value))
with pytest.raises(edtlib.EDTError) as e:
with from_here():
edtlib.Binding("test-bindings-include/allow-not-list.yaml", fname2path)
value_str = str(e.value)
assert value_str.startswith("'property-allowlist' value")
assert value_str.endswith("should be a list")
with pytest.raises(edtlib.EDTError) as e:
with from_here():
edtlib.Binding("test-bindings-include/block-not-list.yaml", fname2path)
value_str = str(e.value)
assert value_str.startswith("'property-blocklist' value")
assert value_str.endswith("should be a list")
with pytest.raises(edtlib.EDTError) as e:
with from_here():
binding = edtlib.Binding("test-bindings-include/include-invalid-keys.yaml", fname2path)
value_str = str(e.value)
assert value_str.startswith(
"'include:' in test-bindings-include/include-invalid-keys.yaml should not have these "
"unexpected contents: ")
assert 'bad-key-1' in value_str
assert 'bad-key-2' in value_str
with pytest.raises(edtlib.EDTError) as e:
with from_here():
binding = edtlib.Binding("test-bindings-include/include-invalid-type.yaml", fname2path)
value_str = str(e.value)
assert value_str.startswith(
"'include:' in test-bindings-include/include-invalid-type.yaml "
"should be a string or list, but has type ")
with pytest.raises(edtlib.EDTError) as e:
with from_here():
binding = edtlib.Binding("test-bindings-include/include-no-name.yaml", fname2path)
value_str = str(e.value)
assert value_str.startswith("'include:' element")
assert value_str.endswith(
"in test-bindings-include/include-no-name.yaml should have a 'name' key")
with from_here():
binding = edtlib.Binding("test-bindings-include/allowlist.yaml", fname2path)
assert set(binding.prop2specs.keys()) == {'x'} # 'x' is allowed
binding = edtlib.Binding("test-bindings-include/empty-allowlist.yaml", fname2path)
assert set(binding.prop2specs.keys()) == set() # nothing is allowed
binding = edtlib.Binding("test-bindings-include/blocklist.yaml", fname2path)
assert set(binding.prop2specs.keys()) == {'y', 'z'} # 'x' is blocked
binding = edtlib.Binding("test-bindings-include/empty-blocklist.yaml", fname2path)
assert set(binding.prop2specs.keys()) == {'x', 'y', 'z'} # nothing is blocked
binding = edtlib.Binding("test-bindings-include/intermixed.yaml", fname2path)
assert set(binding.prop2specs.keys()) == {'x', 'a'}
binding = edtlib.Binding("test-bindings-include/include-no-list.yaml", fname2path)
assert set(binding.prop2specs.keys()) == {'x', 'y', 'z'}
binding = edtlib.Binding("test-bindings-include/filter-child-bindings.yaml", fname2path)
child = binding.child_binding
grandchild = child.child_binding
assert set(binding.prop2specs.keys()) == {'x'}
assert set(child.prop2specs.keys()) == {'child-prop-2'}
assert set(grandchild.prop2specs.keys()) == {'grandchild-prop-1'}
def test_bus():
'''Test 'bus:' and 'on-bus:' in bindings'''
with from_here():
@ -272,6 +408,8 @@ def test_nexus():
assert str(edt.get_node("/gpio-map/source").props["foo-gpios"]) == \
f"<Property, name: foo-gpios, type: phandle-array, value: [<ControllerAndData, controller: <Node /gpio-map/destination in 'test.dts', binding {filename}>, data: OrderedDict([('val', 6)])>, <ControllerAndData, controller: <Node /gpio-map/destination in 'test.dts', binding {filename}>, data: OrderedDict([('val', 5)])>]>"
assert str(edt.get_node("/gpio-map/source").props["foo-gpios"].val[0].basename) == f"gpio"
def test_prop_defaults():
'''Test property default values given in bindings'''
with from_here():
@ -413,6 +551,40 @@ def test_slice_errs(tmp_path):
dts_file,
f"'ranges' property in <Node /sub-1 in '{dts_file}'> has length 8, which is not evenly divisible by 24 (= 4*(<#address-cells> (= 2) + <#address-cells for parent> (= 1) + <#size-cells> (= 3))). Note that #*-cells properties come either from the parent node or from the controller (in the case of 'interrupts').")
def test_bad_compatible(tmp_path):
# An invalid compatible should cause an error, even on a node with
# no binding.
dts_file = tmp_path / "error.dts"
verify_error("""
/dts-v1/;
/ {
foo {
compatible = "no, whitespace";
};
};
""",
dts_file,
r"node '/foo' compatible 'no, whitespace' must match this regular expression: '^[a-zA-Z][a-zA-Z0-9,+\-._]+$'")
def test_wrong_props():
'''Test Node.wrong_props (derived from DT and 'properties:' in the binding)'''
with from_here():
with pytest.raises(edtlib.EDTError) as e:
edtlib.Binding("test-wrong-bindings/wrong-specifier-space-type.yaml", None)
assert ("'specifier-space' in 'properties: wrong-type-for-specifier-space' has type 'phandle', expected 'phandle-array'"
in str(e.value))
with pytest.raises(edtlib.EDTError) as e:
edtlib.Binding("test-wrong-bindings/wrong-phandle-array-name.yaml", None)
value_str = str(e.value)
assert value_str.startswith("'wrong-phandle-array-name' in 'properties:'")
assert value_str.endswith("but no 'specifier-space' was provided.")
def verify_error(dts, dts_file, expected_err):
# Verifies that parsing a file 'dts_file' with the contents 'dts'
# (a string) raises an EDTError with the message 'expected_err'.

View file

@ -5,7 +5,15 @@ envlist=py3
deps =
setuptools-scm
pytest
types-PyYAML
mypy
setenv =
TOXTEMPDIR={envtmpdir}
commands =
python -m pytest {posargs:tests}
python -m mypy --config-file={toxinidir}/tox.ini --package=devicetree
[mypy]
mypy_path=src
ignore_missing_imports=True