#!/usr/bin/env python3 # Copyright (c) 2019 Nordic Semiconductor ASA # SPDX-License-Identifier: BSD-3-Clause import io import sys import edtlib # Test suite for edtlib.py. Run it directly as an executable, in this # directory: # # $ ./testedtlib.py # # test.dts is the test file. test-bindings/ has bindings. The tests mostly use # string comparisons via the various __repr__() methods. def run(): """ Runs all edtlib tests. Immediately exits with status 1 and a message on stderr on test suite failures. """ def fail(msg): sys.exit("test failed: " + msg) def verify_eq(actual, expected): if actual != expected: # Put values on separate lines to make it easy to spot differences fail("not equal (expected value last):\n'{}'\n'{}'" .format(actual, expected)) def verify_streq(actual, expected): verify_eq(str(actual), expected) warnings = io.StringIO() edt = edtlib.EDT("test.dts", ["test-bindings"], warnings) # Deprecated features are tested too, which generate warnings. Verify them. verify_eq(warnings.getvalue(), """\ warning: The 'properties: compatible: constraint: ...' way of specifying the compatible in test-bindings/deprecated.yaml is deprecated. Put 'compatible: "deprecated"' at the top level of the binding instead. warning: the 'inherits:' syntax in test-bindings/deprecated.yaml is deprecated and will be removed - please use 'include: foo.yaml' or 'include: [foo.yaml, bar.yaml]' instead warning: please put 'required: true' instead of 'category: required' in properties: required: ...' in test-bindings/deprecated.yaml - 'category' will be removed warning: please put 'required: false' instead of 'category: optional' in properties: optional: ...' in test-bindings/deprecated.yaml - 'category' will be removed warning: 'sub-node: properties: ...' in test-bindings/deprecated.yaml is deprecated and will be removed - please give a full binding for the child node in 'child-binding:' instead (see binding-template.yaml) warning: "#cells:" in test-bindings/deprecated.yaml is deprecated and will be removed - please put 'interrupt-cells:', 'pwm-cells:', 'gpio-cells:', etc., instead. The name should match the name of the corresponding phandle-array property (see binding-template.yaml) """) # # Test interrupts # verify_streq(edt.get_node("/interrupt-parent-test/node").interrupts, "[, data: {'one': 1, 'two': 2, 'three': 3}>, , data: {'one': 4, 'two': 5, 'three': 6}>]") verify_streq(edt.get_node("/interrupts-extended-test/node").interrupts, "[, data: {'one': 1}>, , data: {'one': 2, 'two': 3}>, , data: {'one': 4, 'two': 5, 'three': 6}>]") verify_streq(edt.get_node("/interrupt-map-test/node@0").interrupts, "[, data: {'one': 0}>, , data: {'one': 0, 'two': 1}>, , data: {'one': 0, 'two': 0, 'three': 2}>]") verify_streq(edt.get_node("/interrupt-map-test/node@1").interrupts, "[, data: {'one': 3}>, , data: {'one': 0, 'two': 4}>, , data: {'one': 0, 'two': 0, 'three': 5}>]") verify_streq(edt.get_node("/interrupt-map-bitops-test/node@70000000E").interrupts, "[, data: {'one': 3, 'two': 2}>]") # # Test 'reg' # verify_streq(edt.get_node("/reg-zero-address-cells/node").regs, "[, ]") verify_streq(edt.get_node("/reg-zero-size-cells/node").regs, "[, ]") verify_streq(edt.get_node("/reg-ranges/parent/node").regs, "[, , , , , ]") verify_streq(edt.get_node("/reg-nested-ranges/grandparent/parent/node").regs, "[]") # # Test Node.parent and Node.children # verify_eq(edt.get_node("/").parent, None) verify_streq(edt.get_node("/parent/child-1").parent, "") verify_streq(edt.get_node("/parent/child-2/grandchild").parent, "") verify_streq(edt.get_node("/parent").children, "{'child-1': , 'child-2': }") verify_eq(edt.get_node("/parent/child-1").children, {}) # # Test 'include:' and the legacy 'inherits: !include ...' # verify_streq(edt.get_node("/binding-include").description, "Parent binding") verify_streq(edt.get_node("/binding-include").props, "{'foo': , 'bar': , 'baz': , 'qaz': }") # # Test 'child/parent-bus:' # verify_streq(edt.get_node("/buses/foo-bus/node").binding_path, "test-bindings/device-on-foo-bus.yaml") verify_streq(edt.get_node("/buses/bar-bus/node").binding_path, "test-bindings/device-on-bar-bus.yaml") # # Test 'child-binding:' # child1 = edt.get_node("/child-binding/child-1") child2 = edt.get_node("/child-binding/child-2") grandchild = edt.get_node("/child-binding/child-1/grandchild") verify_streq(child1.binding_path, "test-bindings/child-binding.yaml") verify_streq(child1.description, "child node") verify_streq(child1.props, "{'child-prop': }") verify_streq(child2.binding_path, "test-bindings/child-binding.yaml") verify_streq(child2.description, "child node") verify_streq(child2.props, "{'child-prop': }") verify_streq(grandchild.binding_path, "test-bindings/child-binding.yaml") verify_streq(grandchild.description, "grandchild node") verify_streq(grandchild.props, "{'grandchild-prop': }") # # Test deprecated 'sub-node' key (replaced with 'child-binding') and # deprecated '#cells' key (replaced with '*-cells') # verify_streq(edt.get_node("/deprecated/sub-node").props, "{'foos': , data: {'foo': 1, 'bar': 2}>]>}") # # Test Node.props (derived from DT and 'properties:' in the binding) # verify_streq(edt.get_node("/props").props["int"], "") verify_streq(edt.get_node("/props").props["existent-boolean"], "") verify_streq(edt.get_node("/props").props["nonexistent-boolean"], "") verify_streq(edt.get_node("/props").props["array"], "") verify_streq(edt.get_node("/props").props["uint8-array"], r"") verify_streq(edt.get_node("/props").props["string"], "") verify_streq(edt.get_node("/props").props["string-array"], "") verify_streq(edt.get_node("/props").props["phandle-ref"], ">") verify_streq(edt.get_node("/props").props["phandle-refs"], ", ]>") verify_streq(edt.get_node("/props").props["phandle-array-foos"], ", data: {'one': 1}>, , data: {'one': 2, 'two': 3}>]>") verify_streq(edt.get_node("/props").props["foo-gpios"], ", data: {'gpio-one': 1}>]>") # # Test -map, via gpio-map (the most common case) # verify_streq(edt.get_node("/gpio-map/source").props["foo-gpios"], ", data: {'val': 6}>, , data: {'val': 5}>]>") # # Test property default values given in bindings # verify_streq(edt.get_node("/defaults").props, r"{'int': , 'array': , 'uint8-array': , 'string': , 'string-array': , 'default-not-used': }") # # Test having multiple directories with bindings, with a different .dts file # edt = edtlib.EDT("test-multidir.dts", ["test-bindings", "test-bindings-2"]) verify_streq(edt.get_node("/in-dir-1").binding_path, "test-bindings/multidir.yaml") verify_streq(edt.get_node("/in-dir-2").binding_path, "test-bindings-2/multidir.yaml") print("all tests passed") if __name__ == "__main__": run()