]> git.sur5r.net Git - u-boot/blob - tools/dtoc/test_fdt.py
dtoc: Drop use of a local dtb buffer
[u-boot] / tools / dtoc / test_fdt.py
1 #!/usr/bin/python
2 # SPDX-License-Identifier: GPL-2.0+
3 # Copyright (c) 2018 Google, Inc
4 # Written by Simon Glass <sjg@chromium.org>
5 #
6
7 from optparse import OptionParser
8 import glob
9 import os
10 import sys
11 import unittest
12
13 # Bring in the patman libraries
14 our_path = os.path.dirname(os.path.realpath(__file__))
15 for dirname in ['../patman', '..']:
16     sys.path.insert(0, os.path.join(our_path, dirname))
17
18 import command
19 import fdt
20 from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL
21 from fdt_util import fdt32_to_cpu
22 import libfdt
23 import test_util
24 import tools
25
26 class TestFdt(unittest.TestCase):
27     """Tests for the Fdt module
28
29     This includes unit tests for some functions and functional tests for the fdt
30     module.
31     """
32     @classmethod
33     def setUpClass(cls):
34         tools.PrepareOutputDir(None)
35
36     @classmethod
37     def tearDownClass(cls):
38         tools._FinaliseForTest()
39
40     def setUp(self):
41         self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
42
43     def testFdt(self):
44         """Test that we can open an Fdt"""
45         self.dtb.Scan()
46         root = self.dtb.GetRoot()
47         self.assertTrue(isinstance(root, fdt.Node))
48
49     def testGetNode(self):
50         """Test the GetNode() method"""
51         node = self.dtb.GetNode('/spl-test')
52         self.assertTrue(isinstance(node, fdt.Node))
53         node = self.dtb.GetNode('/i2c@0/pmic@9')
54         self.assertTrue(isinstance(node, fdt.Node))
55         self.assertEqual('pmic@9', node.name)
56
57     def testFlush(self):
58         """Check that we can flush the device tree out to its file"""
59         fname = self.dtb._fname
60         with open(fname) as fd:
61             data = fd.read()
62         os.remove(fname)
63         with self.assertRaises(IOError):
64             open(fname)
65         self.dtb.Flush()
66         with open(fname) as fd:
67             data = fd.read()
68
69     def testPack(self):
70         """Test that packing a device tree works"""
71         self.dtb.Pack()
72
73     def testGetFdt(self):
74         """Tetst that we can access the raw device-tree data"""
75         self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
76
77     def testGetProps(self):
78         """Tests obtaining a list of properties"""
79         node = self.dtb.GetNode('/spl-test')
80         props = self.dtb.GetProps(node)
81         self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
82                           'intarray', 'intval', 'longbytearray',
83                           'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
84                          sorted(props.keys()))
85
86     def testCheckError(self):
87         """Tests the ChecKError() function"""
88         with self.assertRaises(ValueError) as e:
89             self.dtb.CheckErr(-libfdt.NOTFOUND, 'hello')
90         self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
91
92
93 class TestNode(unittest.TestCase):
94     """Test operation of the Node class"""
95
96     @classmethod
97     def setUpClass(cls):
98         tools.PrepareOutputDir(None)
99
100     @classmethod
101     def tearDownClass(cls):
102         tools._FinaliseForTest()
103
104     def setUp(self):
105         self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
106         self.node = self.dtb.GetNode('/spl-test')
107
108     def testOffset(self):
109         """Tests that we can obtain the offset of a node"""
110         self.assertTrue(self.node.Offset() > 0)
111
112     def testDelete(self):
113         """Tests that we can delete a property"""
114         node2 = self.dtb.GetNode('/spl-test2')
115         offset1 = node2.Offset()
116         self.node.DeleteProp('intval')
117         offset2 = node2.Offset()
118         self.assertTrue(offset2 < offset1)
119         self.node.DeleteProp('intarray')
120         offset3 = node2.Offset()
121         self.assertTrue(offset3 < offset2)
122
123     def testFindNode(self):
124         """Tests that we can find a node using the _FindNode() functoin"""
125         node = self.dtb.GetRoot()._FindNode('i2c@0')
126         self.assertEqual('i2c@0', node.name)
127         subnode = node._FindNode('pmic@9')
128         self.assertEqual('pmic@9', subnode.name)
129
130
131 class TestProp(unittest.TestCase):
132     """Test operation of the Prop class"""
133
134     @classmethod
135     def setUpClass(cls):
136         tools.PrepareOutputDir(None)
137
138     @classmethod
139     def tearDownClass(cls):
140         tools._FinaliseForTest()
141
142     def setUp(self):
143         self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
144         self.node = self.dtb.GetNode('/spl-test')
145         self.fdt = self.dtb.GetFdtObj()
146
147     def testGetEmpty(self):
148         """Tests the GetEmpty() function for the various supported types"""
149         self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
150         self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
151         self.assertEqual(chr(0) * 4, fdt.Prop.GetEmpty(fdt.TYPE_INT))
152         self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
153
154     def testGetOffset(self):
155         """Test we can get the offset of a property"""
156         prop = self.node.props['longbytearray']
157
158         # Add 12, which is sizeof(struct fdt_property), to get to start of data
159         offset = prop.GetOffset() + 12
160         data = self.dtb.GetContents()[offset:offset + len(prop.value)]
161         bytes = [chr(x) for x in data]
162         self.assertEqual(bytes, prop.value)
163
164     def testWiden(self):
165         """Test widening of values"""
166         node2 = self.dtb.GetNode('/spl-test2')
167         prop = self.node.props['intval']
168
169         # No action
170         prop2 = node2.props['intval']
171         prop.Widen(prop2)
172         self.assertEqual(fdt.TYPE_INT, prop.type)
173         self.assertEqual(1, fdt32_to_cpu(prop.value))
174
175         # Convert singla value to array
176         prop2 = self.node.props['intarray']
177         prop.Widen(prop2)
178         self.assertEqual(fdt.TYPE_INT, prop.type)
179         self.assertTrue(isinstance(prop.value, list))
180
181         # A 4-byte array looks like a single integer. When widened by a longer
182         # byte array, it should turn into an array.
183         prop = self.node.props['longbytearray']
184         prop2 = node2.props['longbytearray']
185         self.assertFalse(isinstance(prop2.value, list))
186         self.assertEqual(4, len(prop2.value))
187         prop2.Widen(prop)
188         self.assertTrue(isinstance(prop2.value, list))
189         self.assertEqual(9, len(prop2.value))
190
191         # Similarly for a string array
192         prop = self.node.props['stringval']
193         prop2 = node2.props['stringarray']
194         self.assertFalse(isinstance(prop.value, list))
195         self.assertEqual(7, len(prop.value))
196         prop.Widen(prop2)
197         self.assertTrue(isinstance(prop.value, list))
198         self.assertEqual(3, len(prop.value))
199
200         # Enlarging an existing array
201         prop = self.node.props['stringarray']
202         prop2 = node2.props['stringarray']
203         self.assertTrue(isinstance(prop.value, list))
204         self.assertEqual(2, len(prop.value))
205         prop.Widen(prop2)
206         self.assertTrue(isinstance(prop.value, list))
207         self.assertEqual(3, len(prop.value))
208
209
210 def RunTests(args):
211     """Run all the test we have for the fdt model
212
213     Args:
214         args: List of positional args provided to fdt. This can hold a test
215             name to execute (as in 'fdt -t testFdt', for example)
216     """
217     result = unittest.TestResult()
218     sys.argv = [sys.argv[0]]
219     test_name = args and args[0] or None
220     for module in (TestFdt, TestNode, TestProp):
221         if test_name:
222             try:
223                 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
224             except AttributeError:
225                 continue
226         else:
227             suite = unittest.TestLoader().loadTestsFromTestCase(module)
228         suite.run(result)
229
230     print result
231     for _, err in result.errors:
232         print err
233     for _, err in result.failures:
234         print err
235
236 if __name__ != '__main__':
237     sys.exit(1)
238
239 parser = OptionParser()
240 parser.add_option('-t', '--test', action='store_true', dest='test',
241                   default=False, help='run tests')
242 (options, args) = parser.parse_args()
243
244 # Run our meagre tests
245 if options.test:
246     RunTests(args)