[PATCH 17/17] dtoc: Add tests for the pylibfdt bindings dtoc does not use
Alexey Charkov <[email protected]>
| Newsgroups | org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <[email protected]> |
Exercise additional pylibfdt bindings imported from upstream against the existing dtoc test tree, which already carries a boolean property, a string list, integer arrays and a bus node that overrides #address-cells and #size-cells. The FdtSw cases cover both halves of the geometric growth change: that an out-of-space result at least doubles the buffer, and that a tree needing several expansions still comes out intact. Signed-off-by: Alexey Charkov <[email protected]> --- tools/dtoc/test_fdt.py | 175 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 174 insertions(+), 1 deletion(-) diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index f141f931a949..4ab1365d5318 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -10,6 +10,7 @@ Written by Simon Glass <[email protected]> from argparse import ArgumentParser import os import shutil +import struct import sys import tempfile import unittest @@ -754,6 +755,178 @@ class TestProp(unittest.TestCase): self.dtb.GetFilename()) +class TestPylibfdt(unittest.TestCase): + """Tests for the parts of pylibfdt that dtoc does not itself use + + These bindings come from upstream dtc and have no coverage elsewhere in + U-Boot, so exercise them directly rather than through the Fdt wrapper. + """ + + @classmethod + def setUpClass(cls): + tools.prepare_output_dir(None) + + @classmethod + def tearDownClass(cls): + tools.finalise_output_dir() + + def setUp(self): + self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts')) + self.fdt = self.dtb.GetFdtObj() + self.node = self.fdt.path_offset('/spl-test') + + def test_hasprop(self): + """Test checking for the presence of a property""" + self.assertTrue(self.fdt.hasprop(self.node, 'boolval')) + self.assertTrue(self.fdt.hasprop(self.node, 'intval')) + self.assertFalse(self.fdt.hasprop(self.node, 'missing')) + + def test_hasprop_bad_node(self): + """Test that hasprop() still reports errors other than NOTFOUND""" + with self.assertRaises(libfdt.FdtException) as exc: + self.fdt.hasprop(-1, 'boolval') + self.assertEqual(-libfdt.BADOFFSET, exc.exception.err) + + def test_setprop_bool(self): + """Test creating and deleting a boolean property""" + # Leave room for the new property + self.fdt.resize(self.fdt.totalsize() + 1024) + node = self.fdt.path_offset('/spl-test') + + self.fdt.setprop_bool(node, 'newbool', True) + self.assertTrue(self.fdt.hasprop(node, 'newbool')) + self.assertEqual(b'', self.fdt.getprop(node, 'newbool')) + + # Setting it again should be a no-op + self.fdt.setprop_bool(node, 'newbool', True) + self.assertTrue(self.fdt.hasprop(node, 'newbool')) + + self.fdt.setprop_bool(node, 'newbool', False) + self.assertFalse(self.fdt.hasprop(node, 'newbool')) + + # Deleting it again should also be a no-op + self.fdt.setprop_bool(node, 'newbool', False) + self.assertFalse(self.fdt.hasprop(node, 'newbool')) + + def test_get_path(self): + """Test reading back the full path of a node""" + node = self.fdt.path_offset('/i2c@0/pmic@9') + self.assertEqual('/i2c@0/pmic@9', self.fdt.get_path(node)) + self.assertEqual('/', self.fdt.get_path(0)) + + def test_get_path_no_space(self): + """Test that get_path() retries with a larger buffer as needed""" + node = self.fdt.path_offset('/i2c@0/pmic@9') + self.assertEqual('/i2c@0/pmic@9', self.fdt.get_path(node, size_hint=1)) + + def test_get_path_bad_node(self): + """Test get_path() on an invalid node offset""" + with self.assertRaises(libfdt.FdtException) as exc: + self.fdt.get_path(-1) + self.assertEqual(-libfdt.BADOFFSET, exc.exception.err) + + def test_as_stringlist(self): + """Test decoding a string-list property""" + prop = self.fdt.getprop(self.node, 'stringarray') + self.assertEqual(['multi-word', 'message'], prop.as_stringlist()) + + prop = self.fdt.getprop(self.node, 'stringval') + self.assertEqual(['message'], prop.as_stringlist()) + + def test_as_int_lists(self): + """Test decoding integer-array properties""" + prop = self.fdt.getprop(self.node, 'intarray') + self.assertEqual([2, 3, 4], prop.as_uint32_list()) + self.assertEqual([2, 3, 4], prop.as_int32_list()) + + prop = self.fdt.getprop(self.node, 'int64val') + self.assertEqual([0x123456789abcdef0], prop.as_uint64_list()) + self.assertEqual([0x123456789abcdef0], prop.as_int64_list()) + + def test_as_int_lists_negative(self): + """Test that the signed accessors differ from the unsigned ones""" + self.fdt.resize(self.fdt.totalsize() + 1024) + node = self.fdt.path_offset('/spl-test') + + self.fdt.setprop(node, 'negs32', struct.pack('>ll', -1, -2)) + prop = self.fdt.getprop(node, 'negs32') + self.assertEqual([-1, -2], prop.as_int32_list()) + self.assertEqual([0xffffffff, 0xfffffffe], prop.as_uint32_list()) + + self.fdt.setprop(node, 'negs64', struct.pack('>qq', -1, -2)) + prop = self.fdt.getprop(node, 'negs64') + self.assertEqual([-1, -2], prop.as_int64_list()) + self.assertEqual([0xffffffffffffffff, 0xfffffffffffffffe], + prop.as_uint64_list()) + + def test_address_and_size_cells(self): + """Test reading the cell counts a node uses for its children""" + self.assertEqual(1, self.fdt.address_cells(0)) + self.assertEqual(1, self.fdt.size_cells(0)) + + # i2c@0 overrides both + i2c = self.fdt.path_offset('/i2c@0') + self.assertEqual(1, self.fdt.address_cells(i2c)) + self.assertEqual(0, self.fdt.size_cells(i2c)) + + def test_mem_rsv(self): + """Test adding, reading back and deleting reserve-map records""" + self.assertEqual(0, self.fdt.num_mem_rsv()) + + # Leave room for the new records + self.fdt.resize(self.fdt.totalsize() + 1024) + self.fdt.add_mem_rsv(0xdeadbeef00000000, 0x100000) + self.fdt.add_mem_rsv(0x1000, 0x2000) + self.assertEqual(2, self.fdt.num_mem_rsv()) + self.assertEqual([0xdeadbeef00000000, 0x100000], + list(self.fdt.get_mem_rsv(0))) + self.assertEqual([0x1000, 0x2000], list(self.fdt.get_mem_rsv(1))) + + self.fdt.del_mem_rsv(0) + self.assertEqual(1, self.fdt.num_mem_rsv()) + self.assertEqual([0x1000, 0x2000], list(self.fdt.get_mem_rsv(0))) + + def test_del_mem_rsv_missing(self): + """Test deleting a reserve-map record which is not there""" + with self.assertRaises(libfdt.FdtException) as exc: + self.fdt.del_mem_rsv(0) + self.assertEqual(-libfdt.NOTFOUND, exc.exception.err) + + def test_fdtsw_growth(self): + """Test that running out of space at least doubles the buffer""" + fdtsw = libfdt.FdtSw() + size = len(fdtsw._fdt) + self.assertEqual(fdtsw.INC_SIZE, size) + + self.assertTrue(fdtsw.check_space(-libfdt.NOSPACE)) + self.assertEqual(size * 2, len(fdtsw._fdt)) + + self.assertTrue(fdtsw.check_space(-libfdt.NOSPACE)) + self.assertEqual(size * 4, len(fdtsw._fdt)) + + # Anything that is not an out-of-space error leaves the buffer alone + self.assertFalse(fdtsw.check_space(0)) + self.assertEqual(size * 4, len(fdtsw._fdt)) + + def test_fdtsw_build(self): + """Test building a tree large enough to need several expansions""" + fdtsw = libfdt.FdtSw() + fdtsw.finish_reservemap() + fdtsw.begin_node('') + for i in range(50): + fdtsw.begin_node(f'node{i}') + fdtsw.property('data', b'x' * 200) + fdtsw.end_node() + fdtsw.end_node() + + out = fdtsw.as_fdt() + self.assertGreater(out.totalsize(), fdtsw.INC_SIZE * 4) + for i in range(50): + node = out.path_offset(f'/node{i}') + self.assertEqual(f'/node{i}', out.get_path(node)) + self.assertEqual(b'x' * 200, out.getprop(node, 'data')) + + class TestFdtUtil(unittest.TestCase): """Tests for the fdt_util module @@ -970,7 +1143,7 @@ def run_tests(names, processes): test_name = names[0] if names else None result = test_util.run_test_suites( 'test_fdt', False, False, False, False, processes, test_name, None, - [TestFdt, TestNode, TestProp, TestFdtUtil]) + [TestFdt, TestNode, TestProp, TestPylibfdt, TestFdtUtil]) return (0 if result.wasSuccessful() else 1) -- 2.54.0