xref: /openbmc/u-boot/tools/dtoc/test_fdt.py (revision 96066240)
12ba98753SSimon Glass#!/usr/bin/python
22ba98753SSimon Glass# SPDX-License-Identifier: GPL-2.0+
32ba98753SSimon Glass# Copyright (c) 2018 Google, Inc
42ba98753SSimon Glass# Written by Simon Glass <sjg@chromium.org>
52ba98753SSimon Glass#
62ba98753SSimon Glass
72ba98753SSimon Glassfrom optparse import OptionParser
82ba98753SSimon Glassimport glob
92ba98753SSimon Glassimport os
102ba98753SSimon Glassimport sys
112ba98753SSimon Glassimport unittest
122ba98753SSimon Glass
132ba98753SSimon Glass# Bring in the patman libraries
142ba98753SSimon Glassour_path = os.path.dirname(os.path.realpath(__file__))
152ba98753SSimon Glassfor dirname in ['../patman', '..']:
162ba98753SSimon Glass    sys.path.insert(0, os.path.join(our_path, dirname))
172ba98753SSimon Glass
182ba98753SSimon Glassimport command
192ba98753SSimon Glassimport fdt
202ba98753SSimon Glassfrom fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL
212ba98753SSimon Glassfrom fdt_util import fdt32_to_cpu
222ba98753SSimon Glassimport libfdt
232ba98753SSimon Glassimport test_util
242ba98753SSimon Glassimport tools
252ba98753SSimon Glass
262ba98753SSimon Glassclass TestFdt(unittest.TestCase):
272ba98753SSimon Glass    """Tests for the Fdt module
282ba98753SSimon Glass
292ba98753SSimon Glass    This includes unit tests for some functions and functional tests for the fdt
302ba98753SSimon Glass    module.
312ba98753SSimon Glass    """
322ba98753SSimon Glass    @classmethod
332ba98753SSimon Glass    def setUpClass(cls):
342ba98753SSimon Glass        tools.PrepareOutputDir(None)
352ba98753SSimon Glass
362ba98753SSimon Glass    @classmethod
372ba98753SSimon Glass    def tearDownClass(cls):
382ba98753SSimon Glass        tools._FinaliseForTest()
392ba98753SSimon Glass
402ba98753SSimon Glass    def setUp(self):
412ba98753SSimon Glass        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
422ba98753SSimon Glass
432ba98753SSimon Glass    def testFdt(self):
442ba98753SSimon Glass        """Test that we can open an Fdt"""
452ba98753SSimon Glass        self.dtb.Scan()
462ba98753SSimon Glass        root = self.dtb.GetRoot()
472ba98753SSimon Glass        self.assertTrue(isinstance(root, fdt.Node))
482ba98753SSimon Glass
492ba98753SSimon Glass    def testGetNode(self):
502ba98753SSimon Glass        """Test the GetNode() method"""
512ba98753SSimon Glass        node = self.dtb.GetNode('/spl-test')
522ba98753SSimon Glass        self.assertTrue(isinstance(node, fdt.Node))
532ba98753SSimon Glass        node = self.dtb.GetNode('/i2c@0/pmic@9')
542ba98753SSimon Glass        self.assertTrue(isinstance(node, fdt.Node))
552ba98753SSimon Glass        self.assertEqual('pmic@9', node.name)
562ba98753SSimon Glass
572ba98753SSimon Glass    def testFlush(self):
582ba98753SSimon Glass        """Check that we can flush the device tree out to its file"""
592ba98753SSimon Glass        fname = self.dtb._fname
602ba98753SSimon Glass        with open(fname) as fd:
612ba98753SSimon Glass            data = fd.read()
622ba98753SSimon Glass        os.remove(fname)
632ba98753SSimon Glass        with self.assertRaises(IOError):
642ba98753SSimon Glass            open(fname)
652ba98753SSimon Glass        self.dtb.Flush()
662ba98753SSimon Glass        with open(fname) as fd:
672ba98753SSimon Glass            data = fd.read()
682ba98753SSimon Glass
692ba98753SSimon Glass    def testPack(self):
702ba98753SSimon Glass        """Test that packing a device tree works"""
712ba98753SSimon Glass        self.dtb.Pack()
722ba98753SSimon Glass
732ba98753SSimon Glass    def testGetFdt(self):
742ba98753SSimon Glass        """Tetst that we can access the raw device-tree data"""
75*96066240SSimon Glass        self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
762ba98753SSimon Glass
772ba98753SSimon Glass    def testGetProps(self):
782ba98753SSimon Glass        """Tests obtaining a list of properties"""
792ba98753SSimon Glass        node = self.dtb.GetNode('/spl-test')
802ba98753SSimon Glass        props = self.dtb.GetProps(node)
812ba98753SSimon Glass        self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
822ba98753SSimon Glass                          'intarray', 'intval', 'longbytearray',
832ba98753SSimon Glass                          'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
842ba98753SSimon Glass                         sorted(props.keys()))
852ba98753SSimon Glass
862ba98753SSimon Glass    def testCheckError(self):
872ba98753SSimon Glass        """Tests the ChecKError() function"""
882ba98753SSimon Glass        with self.assertRaises(ValueError) as e:
892ba98753SSimon Glass            self.dtb.CheckErr(-libfdt.NOTFOUND, 'hello')
902ba98753SSimon Glass        self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
912ba98753SSimon Glass
922ba98753SSimon Glass
932ba98753SSimon Glassclass TestNode(unittest.TestCase):
942ba98753SSimon Glass    """Test operation of the Node class"""
952ba98753SSimon Glass
962ba98753SSimon Glass    @classmethod
972ba98753SSimon Glass    def setUpClass(cls):
982ba98753SSimon Glass        tools.PrepareOutputDir(None)
992ba98753SSimon Glass
1002ba98753SSimon Glass    @classmethod
1012ba98753SSimon Glass    def tearDownClass(cls):
1022ba98753SSimon Glass        tools._FinaliseForTest()
1032ba98753SSimon Glass
1042ba98753SSimon Glass    def setUp(self):
1052ba98753SSimon Glass        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
1062ba98753SSimon Glass        self.node = self.dtb.GetNode('/spl-test')
1072ba98753SSimon Glass
1082ba98753SSimon Glass    def testOffset(self):
1092ba98753SSimon Glass        """Tests that we can obtain the offset of a node"""
1102ba98753SSimon Glass        self.assertTrue(self.node.Offset() > 0)
1112ba98753SSimon Glass
1122ba98753SSimon Glass    def testDelete(self):
1132ba98753SSimon Glass        """Tests that we can delete a property"""
1142ba98753SSimon Glass        node2 = self.dtb.GetNode('/spl-test2')
1152ba98753SSimon Glass        offset1 = node2.Offset()
1162ba98753SSimon Glass        self.node.DeleteProp('intval')
1172ba98753SSimon Glass        offset2 = node2.Offset()
1182ba98753SSimon Glass        self.assertTrue(offset2 < offset1)
1192ba98753SSimon Glass        self.node.DeleteProp('intarray')
1202ba98753SSimon Glass        offset3 = node2.Offset()
1212ba98753SSimon Glass        self.assertTrue(offset3 < offset2)
1222ba98753SSimon Glass
1232ba98753SSimon Glass    def testFindNode(self):
1242ba98753SSimon Glass        """Tests that we can find a node using the _FindNode() functoin"""
1252ba98753SSimon Glass        node = self.dtb.GetRoot()._FindNode('i2c@0')
1262ba98753SSimon Glass        self.assertEqual('i2c@0', node.name)
1272ba98753SSimon Glass        subnode = node._FindNode('pmic@9')
1282ba98753SSimon Glass        self.assertEqual('pmic@9', subnode.name)
1292ba98753SSimon Glass
1302ba98753SSimon Glass
1312ba98753SSimon Glassclass TestProp(unittest.TestCase):
1322ba98753SSimon Glass    """Test operation of the Prop class"""
1332ba98753SSimon Glass
1342ba98753SSimon Glass    @classmethod
1352ba98753SSimon Glass    def setUpClass(cls):
1362ba98753SSimon Glass        tools.PrepareOutputDir(None)
1372ba98753SSimon Glass
1382ba98753SSimon Glass    @classmethod
1392ba98753SSimon Glass    def tearDownClass(cls):
1402ba98753SSimon Glass        tools._FinaliseForTest()
1412ba98753SSimon Glass
1422ba98753SSimon Glass    def setUp(self):
1432ba98753SSimon Glass        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
1442ba98753SSimon Glass        self.node = self.dtb.GetNode('/spl-test')
1452ba98753SSimon Glass        self.fdt = self.dtb.GetFdtObj()
1462ba98753SSimon Glass
1472ba98753SSimon Glass    def testGetEmpty(self):
1482ba98753SSimon Glass        """Tests the GetEmpty() function for the various supported types"""
1492ba98753SSimon Glass        self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
1502ba98753SSimon Glass        self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
1512ba98753SSimon Glass        self.assertEqual(chr(0) * 4, fdt.Prop.GetEmpty(fdt.TYPE_INT))
1522ba98753SSimon Glass        self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
1532ba98753SSimon Glass
1542ba98753SSimon Glass    def testGetOffset(self):
1552ba98753SSimon Glass        """Test we can get the offset of a property"""
1562ba98753SSimon Glass        prop = self.node.props['longbytearray']
1572ba98753SSimon Glass
1582ba98753SSimon Glass        # Add 12, which is sizeof(struct fdt_property), to get to start of data
1592ba98753SSimon Glass        offset = prop.GetOffset() + 12
160*96066240SSimon Glass        data = self.dtb.GetContents()[offset:offset + len(prop.value)]
1612ba98753SSimon Glass        bytes = [chr(x) for x in data]
1622ba98753SSimon Glass        self.assertEqual(bytes, prop.value)
1632ba98753SSimon Glass
1642ba98753SSimon Glass    def testWiden(self):
1652ba98753SSimon Glass        """Test widening of values"""
1662ba98753SSimon Glass        node2 = self.dtb.GetNode('/spl-test2')
1672ba98753SSimon Glass        prop = self.node.props['intval']
1682ba98753SSimon Glass
1692ba98753SSimon Glass        # No action
1702ba98753SSimon Glass        prop2 = node2.props['intval']
1712ba98753SSimon Glass        prop.Widen(prop2)
1722ba98753SSimon Glass        self.assertEqual(fdt.TYPE_INT, prop.type)
1732ba98753SSimon Glass        self.assertEqual(1, fdt32_to_cpu(prop.value))
1742ba98753SSimon Glass
1752ba98753SSimon Glass        # Convert singla value to array
1762ba98753SSimon Glass        prop2 = self.node.props['intarray']
1772ba98753SSimon Glass        prop.Widen(prop2)
1782ba98753SSimon Glass        self.assertEqual(fdt.TYPE_INT, prop.type)
1792ba98753SSimon Glass        self.assertTrue(isinstance(prop.value, list))
1802ba98753SSimon Glass
1812ba98753SSimon Glass        # A 4-byte array looks like a single integer. When widened by a longer
1822ba98753SSimon Glass        # byte array, it should turn into an array.
1832ba98753SSimon Glass        prop = self.node.props['longbytearray']
1842ba98753SSimon Glass        prop2 = node2.props['longbytearray']
1852ba98753SSimon Glass        self.assertFalse(isinstance(prop2.value, list))
1862ba98753SSimon Glass        self.assertEqual(4, len(prop2.value))
1872ba98753SSimon Glass        prop2.Widen(prop)
1882ba98753SSimon Glass        self.assertTrue(isinstance(prop2.value, list))
1892ba98753SSimon Glass        self.assertEqual(9, len(prop2.value))
1902ba98753SSimon Glass
1912ba98753SSimon Glass        # Similarly for a string array
1922ba98753SSimon Glass        prop = self.node.props['stringval']
1932ba98753SSimon Glass        prop2 = node2.props['stringarray']
1942ba98753SSimon Glass        self.assertFalse(isinstance(prop.value, list))
1952ba98753SSimon Glass        self.assertEqual(7, len(prop.value))
1962ba98753SSimon Glass        prop.Widen(prop2)
1972ba98753SSimon Glass        self.assertTrue(isinstance(prop.value, list))
1982ba98753SSimon Glass        self.assertEqual(3, len(prop.value))
1992ba98753SSimon Glass
2002ba98753SSimon Glass        # Enlarging an existing array
2012ba98753SSimon Glass        prop = self.node.props['stringarray']
2022ba98753SSimon Glass        prop2 = node2.props['stringarray']
2032ba98753SSimon Glass        self.assertTrue(isinstance(prop.value, list))
2042ba98753SSimon Glass        self.assertEqual(2, len(prop.value))
2052ba98753SSimon Glass        prop.Widen(prop2)
2062ba98753SSimon Glass        self.assertTrue(isinstance(prop.value, list))
2072ba98753SSimon Glass        self.assertEqual(3, len(prop.value))
2082ba98753SSimon Glass
2092ba98753SSimon Glass
2102ba98753SSimon Glassdef RunTests(args):
2112ba98753SSimon Glass    """Run all the test we have for the fdt model
2122ba98753SSimon Glass
2132ba98753SSimon Glass    Args:
2142ba98753SSimon Glass        args: List of positional args provided to fdt. This can hold a test
2152ba98753SSimon Glass            name to execute (as in 'fdt -t testFdt', for example)
2162ba98753SSimon Glass    """
2172ba98753SSimon Glass    result = unittest.TestResult()
2182ba98753SSimon Glass    sys.argv = [sys.argv[0]]
2192ba98753SSimon Glass    test_name = args and args[0] or None
2202ba98753SSimon Glass    for module in (TestFdt, TestNode, TestProp):
2212ba98753SSimon Glass        if test_name:
2222ba98753SSimon Glass            try:
2232ba98753SSimon Glass                suite = unittest.TestLoader().loadTestsFromName(test_name, module)
2242ba98753SSimon Glass            except AttributeError:
2252ba98753SSimon Glass                continue
2262ba98753SSimon Glass        else:
2272ba98753SSimon Glass            suite = unittest.TestLoader().loadTestsFromTestCase(module)
2282ba98753SSimon Glass        suite.run(result)
2292ba98753SSimon Glass
2302ba98753SSimon Glass    print result
2312ba98753SSimon Glass    for _, err in result.errors:
2322ba98753SSimon Glass        print err
2332ba98753SSimon Glass    for _, err in result.failures:
2342ba98753SSimon Glass        print err
2352ba98753SSimon Glass
2362ba98753SSimon Glassif __name__ != '__main__':
2372ba98753SSimon Glass    sys.exit(1)
2382ba98753SSimon Glass
2392ba98753SSimon Glassparser = OptionParser()
2402ba98753SSimon Glassparser.add_option('-t', '--test', action='store_true', dest='test',
2412ba98753SSimon Glass                  default=False, help='run tests')
2422ba98753SSimon Glass(options, args) = parser.parse_args()
2432ba98753SSimon Glass
2442ba98753SSimon Glass# Run our meagre tests
2452ba98753SSimon Glassif options.test:
2462ba98753SSimon Glass    RunTests(args)
247