blob: ba660ca9b7552bfe07451ce420cb73fa0bde6741 [file] [log] [blame]
Simon Glass0ed50752018-07-06 10:27:24 -06001#!/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
7from optparse import OptionParser
8import glob
9import os
10import sys
11import unittest
12
13# Bring in the patman libraries
14our_path = os.path.dirname(os.path.realpath(__file__))
15for dirname in ['../patman', '..']:
16 sys.path.insert(0, os.path.join(our_path, dirname))
17
18import command
19import fdt
20from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL
21from fdt_util import fdt32_to_cpu
22import libfdt
23import test_util
24import tools
25
26class 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.GetFdt(), 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
93class 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
131class 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._fdt[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
210def 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
236if __name__ != '__main__':
237 sys.exit(1)
238
239parser = OptionParser()
240parser.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
245if options.test:
246 RunTests(args)