blob: c25248ca1f9ed1ec140d286d7ee4a1e3e0d5e015 [file] [log] [blame]
Simon Glass2ba98752018-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
Simon Glass90a81322019-05-17 22:00:31 -06007from __future__ import print_function
8
Simon Glass2ba98752018-07-06 10:27:24 -06009from optparse import OptionParser
10import glob
11import os
12import sys
13import unittest
14
15# Bring in the patman libraries
16our_path = os.path.dirname(os.path.realpath(__file__))
17for dirname in ['../patman', '..']:
18 sys.path.insert(0, os.path.join(our_path, dirname))
19
20import command
21import fdt
Simon Glassb5f0daf2019-05-17 22:00:41 -060022from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
Simon Glass2a2d91d2018-07-06 10:27:28 -060023import fdt_util
Simon Glass2ba98752018-07-06 10:27:24 -060024from fdt_util import fdt32_to_cpu
25import libfdt
26import test_util
27import tools
28
Simon Glassf9b88b32018-07-06 10:27:29 -060029def _GetPropertyValue(dtb, node, prop_name):
30 """Low-level function to get the property value based on its offset
31
32 This looks directly in the device tree at the property's offset to find
33 its value. It is useful as a check that the property is in the correct
34 place.
35
36 Args:
37 node: Node to look in
38 prop_name: Property name to find
39
40 Returns:
41 Tuple:
42 Prop object found
43 Value of property as a string (found using property offset)
44 """
45 prop = node.props[prop_name]
46
47 # Add 12, which is sizeof(struct fdt_property), to get to start of data
48 offset = prop.GetOffset() + 12
49 data = dtb.GetContents()[offset:offset + len(prop.value)]
Simon Glassf6b64812019-05-17 22:00:36 -060050 return prop, [tools.ToChar(x) for x in data]
Simon Glassf9b88b32018-07-06 10:27:29 -060051
52
Simon Glass2ba98752018-07-06 10:27:24 -060053class TestFdt(unittest.TestCase):
54 """Tests for the Fdt module
55
56 This includes unit tests for some functions and functional tests for the fdt
57 module.
58 """
59 @classmethod
60 def setUpClass(cls):
61 tools.PrepareOutputDir(None)
62
63 @classmethod
64 def tearDownClass(cls):
Simon Glasse0e62752018-10-01 21:12:41 -060065 tools.FinaliseOutputDir()
Simon Glass2ba98752018-07-06 10:27:24 -060066
67 def setUp(self):
68 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
69
70 def testFdt(self):
71 """Test that we can open an Fdt"""
72 self.dtb.Scan()
73 root = self.dtb.GetRoot()
74 self.assertTrue(isinstance(root, fdt.Node))
75
76 def testGetNode(self):
77 """Test the GetNode() method"""
78 node = self.dtb.GetNode('/spl-test')
79 self.assertTrue(isinstance(node, fdt.Node))
80 node = self.dtb.GetNode('/i2c@0/pmic@9')
81 self.assertTrue(isinstance(node, fdt.Node))
82 self.assertEqual('pmic@9', node.name)
Simon Glass2a2d91d2018-07-06 10:27:28 -060083 self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
Simon Glass2ba98752018-07-06 10:27:24 -060084
85 def testFlush(self):
86 """Check that we can flush the device tree out to its file"""
87 fname = self.dtb._fname
Simon Glass2ab6e132019-05-17 22:00:39 -060088 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-07-06 10:27:24 -060089 data = fd.read()
90 os.remove(fname)
91 with self.assertRaises(IOError):
Simon Glass2ab6e132019-05-17 22:00:39 -060092 open(fname, 'rb')
Simon Glass2ba98752018-07-06 10:27:24 -060093 self.dtb.Flush()
Simon Glass2ab6e132019-05-17 22:00:39 -060094 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-07-06 10:27:24 -060095 data = fd.read()
96
97 def testPack(self):
98 """Test that packing a device tree works"""
99 self.dtb.Pack()
100
101 def testGetFdt(self):
102 """Tetst that we can access the raw device-tree data"""
Simon Glass96066242018-07-06 10:27:27 -0600103 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
Simon Glass2ba98752018-07-06 10:27:24 -0600104
105 def testGetProps(self):
106 """Tests obtaining a list of properties"""
107 node = self.dtb.GetNode('/spl-test')
108 props = self.dtb.GetProps(node)
109 self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
Simon Glass2a2d91d2018-07-06 10:27:28 -0600110 'intarray', 'intval', 'longbytearray', 'notstring',
Simon Glass2ba98752018-07-06 10:27:24 -0600111 'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
112 sorted(props.keys()))
113
114 def testCheckError(self):
115 """Tests the ChecKError() function"""
116 with self.assertRaises(ValueError) as e:
Simon Glass2a2d91d2018-07-06 10:27:28 -0600117 fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
Simon Glass2ba98752018-07-06 10:27:24 -0600118 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
119
Simon Glass94a7c602018-07-17 13:25:46 -0600120 def testGetFdt(self):
121 node = self.dtb.GetNode('/spl-test')
122 self.assertEqual(self.dtb, node.GetFdt())
Simon Glass2ba98752018-07-06 10:27:24 -0600123
Simon Glassb5f0daf2019-05-17 22:00:41 -0600124 def testBytesToValue(self):
125 self.assertEqual(BytesToValue(b'this\0is\0'),
126 (TYPE_STRING, ['this', 'is']))
127
Simon Glass2ba98752018-07-06 10:27:24 -0600128class TestNode(unittest.TestCase):
129 """Test operation of the Node class"""
130
131 @classmethod
132 def setUpClass(cls):
133 tools.PrepareOutputDir(None)
134
135 @classmethod
136 def tearDownClass(cls):
Simon Glasse0e62752018-10-01 21:12:41 -0600137 tools.FinaliseOutputDir()
Simon Glass2ba98752018-07-06 10:27:24 -0600138
139 def setUp(self):
140 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
141 self.node = self.dtb.GetNode('/spl-test')
142
143 def testOffset(self):
144 """Tests that we can obtain the offset of a node"""
145 self.assertTrue(self.node.Offset() > 0)
146
147 def testDelete(self):
148 """Tests that we can delete a property"""
149 node2 = self.dtb.GetNode('/spl-test2')
150 offset1 = node2.Offset()
151 self.node.DeleteProp('intval')
152 offset2 = node2.Offset()
153 self.assertTrue(offset2 < offset1)
154 self.node.DeleteProp('intarray')
155 offset3 = node2.Offset()
156 self.assertTrue(offset3 < offset2)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600157 with self.assertRaises(libfdt.FdtException):
158 self.node.DeleteProp('missing')
Simon Glass2ba98752018-07-06 10:27:24 -0600159
Simon Glassf9b88b32018-07-06 10:27:29 -0600160 def testDeleteGetOffset(self):
161 """Test that property offset update when properties are deleted"""
162 self.node.DeleteProp('intval')
163 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
164 self.assertEqual(prop.value, value)
165
Simon Glass2ba98752018-07-06 10:27:24 -0600166 def testFindNode(self):
Simon Glass1d858882018-07-17 13:25:41 -0600167 """Tests that we can find a node using the FindNode() functoin"""
168 node = self.dtb.GetRoot().FindNode('i2c@0')
Simon Glass2ba98752018-07-06 10:27:24 -0600169 self.assertEqual('i2c@0', node.name)
Simon Glass1d858882018-07-17 13:25:41 -0600170 subnode = node.FindNode('pmic@9')
Simon Glass2ba98752018-07-06 10:27:24 -0600171 self.assertEqual('pmic@9', subnode.name)
Simon Glass1d858882018-07-17 13:25:41 -0600172 self.assertEqual(None, node.FindNode('missing'))
Simon Glass2ba98752018-07-06 10:27:24 -0600173
Simon Glassf9b88b32018-07-06 10:27:29 -0600174 def testRefreshMissingNode(self):
175 """Test refreshing offsets when an extra node is present in dtb"""
176 # Delete it from our tables, not the device tree
177 del self.dtb._root.subnodes[-1]
178 with self.assertRaises(ValueError) as e:
179 self.dtb.Refresh()
180 self.assertIn('Internal error, offset', str(e.exception))
181
182 def testRefreshExtraNode(self):
183 """Test refreshing offsets when an expected node is missing"""
184 # Delete it from the device tre, not our tables
185 self.dtb.GetFdtObj().del_node(self.node.Offset())
186 with self.assertRaises(ValueError) as e:
187 self.dtb.Refresh()
188 self.assertIn('Internal error, node name mismatch '
189 'spl-test != spl-test2', str(e.exception))
190
191 def testRefreshMissingProp(self):
192 """Test refreshing offsets when an extra property is present in dtb"""
193 # Delete it from our tables, not the device tree
194 del self.node.props['notstring']
195 with self.assertRaises(ValueError) as e:
196 self.dtb.Refresh()
197 self.assertIn("Internal error, property 'notstring' missing, offset ",
198 str(e.exception))
199
Simon Glass94a7c602018-07-17 13:25:46 -0600200 def testLookupPhandle(self):
201 """Test looking up a single phandle"""
202 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
203 node = dtb.GetNode('/phandle-source2')
204 prop = node.props['clocks']
205 target = dtb.GetNode('/phandle-target')
206 self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
207
Simon Glass2ba98752018-07-06 10:27:24 -0600208
209class TestProp(unittest.TestCase):
210 """Test operation of the Prop class"""
211
212 @classmethod
213 def setUpClass(cls):
214 tools.PrepareOutputDir(None)
215
216 @classmethod
217 def tearDownClass(cls):
Simon Glasse0e62752018-10-01 21:12:41 -0600218 tools.FinaliseOutputDir()
Simon Glass2ba98752018-07-06 10:27:24 -0600219
220 def setUp(self):
221 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
222 self.node = self.dtb.GetNode('/spl-test')
223 self.fdt = self.dtb.GetFdtObj()
224
Simon Glassb9066ff2018-07-06 10:27:30 -0600225 def testMissingNode(self):
226 self.assertEqual(None, self.dtb.GetNode('missing'))
227
Simon Glass2a2d91d2018-07-06 10:27:28 -0600228 def testPhandle(self):
229 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
Simon Glass760b7172018-07-06 10:27:31 -0600230 node = dtb.GetNode('/phandle-source2')
231 prop = node.props['clocks']
232 self.assertTrue(fdt32_to_cpu(prop.value) > 0)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600233
234 def _ConvertProp(self, prop_name):
235 """Helper function to look up a property in self.node and return it
236
237 Args:
238 Property name to find
239
240 Return fdt.Prop object for this property
241 """
Simon Glass50c59522018-07-26 14:02:13 -0600242 p = self.fdt.getprop(self.node.Offset(), prop_name)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600243 return fdt.Prop(self.node, -1, prop_name, p)
244
245 def testMakeProp(self):
246 """Test we can convert all the the types that are supported"""
247 prop = self._ConvertProp('boolval')
248 self.assertEqual(fdt.TYPE_BOOL, prop.type)
249 self.assertEqual(True, prop.value)
250
251 prop = self._ConvertProp('intval')
252 self.assertEqual(fdt.TYPE_INT, prop.type)
253 self.assertEqual(1, fdt32_to_cpu(prop.value))
254
255 prop = self._ConvertProp('intarray')
256 self.assertEqual(fdt.TYPE_INT, prop.type)
257 val = [fdt32_to_cpu(val) for val in prop.value]
258 self.assertEqual([2, 3, 4], val)
259
260 prop = self._ConvertProp('byteval')
261 self.assertEqual(fdt.TYPE_BYTE, prop.type)
262 self.assertEqual(5, ord(prop.value))
263
264 prop = self._ConvertProp('longbytearray')
265 self.assertEqual(fdt.TYPE_BYTE, prop.type)
266 val = [ord(val) for val in prop.value]
267 self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
268
269 prop = self._ConvertProp('stringval')
270 self.assertEqual(fdt.TYPE_STRING, prop.type)
271 self.assertEqual('message', prop.value)
272
273 prop = self._ConvertProp('stringarray')
274 self.assertEqual(fdt.TYPE_STRING, prop.type)
275 self.assertEqual(['multi-word', 'message'], prop.value)
276
277 prop = self._ConvertProp('notstring')
278 self.assertEqual(fdt.TYPE_BYTE, prop.type)
279 val = [ord(val) for val in prop.value]
280 self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
281
Simon Glass2ba98752018-07-06 10:27:24 -0600282 def testGetEmpty(self):
283 """Tests the GetEmpty() function for the various supported types"""
284 self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
285 self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
Simon Glass194b8d52019-05-17 22:00:33 -0600286 self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
Simon Glass2ba98752018-07-06 10:27:24 -0600287 self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
288
289 def testGetOffset(self):
290 """Test we can get the offset of a property"""
Simon Glassf9b88b32018-07-06 10:27:29 -0600291 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
292 self.assertEqual(prop.value, value)
Simon Glass2ba98752018-07-06 10:27:24 -0600293
294 def testWiden(self):
295 """Test widening of values"""
296 node2 = self.dtb.GetNode('/spl-test2')
297 prop = self.node.props['intval']
298
299 # No action
300 prop2 = node2.props['intval']
301 prop.Widen(prop2)
302 self.assertEqual(fdt.TYPE_INT, prop.type)
303 self.assertEqual(1, fdt32_to_cpu(prop.value))
304
305 # Convert singla value to array
306 prop2 = self.node.props['intarray']
307 prop.Widen(prop2)
308 self.assertEqual(fdt.TYPE_INT, prop.type)
309 self.assertTrue(isinstance(prop.value, list))
310
311 # A 4-byte array looks like a single integer. When widened by a longer
312 # byte array, it should turn into an array.
313 prop = self.node.props['longbytearray']
314 prop2 = node2.props['longbytearray']
315 self.assertFalse(isinstance(prop2.value, list))
316 self.assertEqual(4, len(prop2.value))
317 prop2.Widen(prop)
318 self.assertTrue(isinstance(prop2.value, list))
319 self.assertEqual(9, len(prop2.value))
320
321 # Similarly for a string array
322 prop = self.node.props['stringval']
323 prop2 = node2.props['stringarray']
324 self.assertFalse(isinstance(prop.value, list))
325 self.assertEqual(7, len(prop.value))
326 prop.Widen(prop2)
327 self.assertTrue(isinstance(prop.value, list))
328 self.assertEqual(3, len(prop.value))
329
330 # Enlarging an existing array
331 prop = self.node.props['stringarray']
332 prop2 = node2.props['stringarray']
333 self.assertTrue(isinstance(prop.value, list))
334 self.assertEqual(2, len(prop.value))
335 prop.Widen(prop2)
336 self.assertTrue(isinstance(prop.value, list))
337 self.assertEqual(3, len(prop.value))
338
Simon Glass116adec2018-07-06 10:27:38 -0600339 def testAdd(self):
340 """Test adding properties"""
341 self.fdt.pack()
342 # This function should automatically expand the device tree
343 self.node.AddZeroProp('one')
344 self.node.AddZeroProp('two')
345 self.node.AddZeroProp('three')
Simon Glassfa80c252018-09-14 04:57:13 -0600346 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-07-06 10:27:38 -0600347
348 # Updating existing properties should be OK, since the device-tree size
349 # does not change
350 self.fdt.pack()
351 self.node.SetInt('one', 1)
352 self.node.SetInt('two', 2)
353 self.node.SetInt('three', 3)
Simon Glassfa80c252018-09-14 04:57:13 -0600354 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600355
356 # This should fail since it would need to increase the device-tree size
Simon Glassfa80c252018-09-14 04:57:13 -0600357 self.node.AddZeroProp('four')
Simon Glass116adec2018-07-06 10:27:38 -0600358 with self.assertRaises(libfdt.FdtException) as e:
Simon Glassfa80c252018-09-14 04:57:13 -0600359 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600360 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
Simon Glass64349612018-09-14 04:57:16 -0600361 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-07-06 10:27:38 -0600362
Simon Glassfa80c252018-09-14 04:57:13 -0600363 def testAddNode(self):
364 self.fdt.pack()
Simon Glasse21c27a2018-09-14 04:57:15 -0600365 self.node.AddSubnode('subnode')
366 with self.assertRaises(libfdt.FdtException) as e:
367 self.dtb.Sync(auto_resize=False)
368 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
369
370 self.dtb.Sync(auto_resize=True)
371 offset = self.fdt.path_offset('/spl-test/subnode')
372 self.assertTrue(offset > 0)
Simon Glassfa80c252018-09-14 04:57:13 -0600373
Simon Glass64349612018-09-14 04:57:16 -0600374 def testAddMore(self):
375 """Test various other methods for adding and setting properties"""
376 self.node.AddZeroProp('one')
377 self.dtb.Sync(auto_resize=True)
378 data = self.fdt.getprop(self.node.Offset(), 'one')
379 self.assertEqual(0, fdt32_to_cpu(data))
380
381 self.node.SetInt('one', 1)
382 self.dtb.Sync(auto_resize=False)
383 data = self.fdt.getprop(self.node.Offset(), 'one')
384 self.assertEqual(1, fdt32_to_cpu(data))
385
386 val = '123' + chr(0) + '456'
387 self.node.AddString('string', val)
388 self.dtb.Sync(auto_resize=True)
389 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glassf6b64812019-05-17 22:00:36 -0600390 self.assertEqual(tools.ToBytes(val) + b'\0', data)
Simon Glass64349612018-09-14 04:57:16 -0600391
392 self.fdt.pack()
393 self.node.SetString('string', val + 'x')
394 with self.assertRaises(libfdt.FdtException) as e:
395 self.dtb.Sync(auto_resize=False)
396 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
397 self.node.SetString('string', val[:-1])
398
399 prop = self.node.props['string']
Simon Glassf6b64812019-05-17 22:00:36 -0600400 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600401 self.dtb.Sync(auto_resize=False)
402 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glassf6b64812019-05-17 22:00:36 -0600403 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-09-14 04:57:16 -0600404
405 self.node.AddEmptyProp('empty', 5)
406 self.dtb.Sync(auto_resize=True)
407 prop = self.node.props['empty']
Simon Glassf6b64812019-05-17 22:00:36 -0600408 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600409 self.dtb.Sync(auto_resize=False)
410 data = self.fdt.getprop(self.node.Offset(), 'empty')
Simon Glassf6b64812019-05-17 22:00:36 -0600411 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-09-14 04:57:16 -0600412
Simon Glassf6b64812019-05-17 22:00:36 -0600413 self.node.SetData('empty', b'123')
414 self.assertEqual(b'123', prop.bytes)
Simon Glass64349612018-09-14 04:57:16 -0600415
Simon Glass746aee32018-09-14 04:57:17 -0600416 def testFromData(self):
417 dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
418 self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
419
420 self.node.AddEmptyProp('empty', 5)
421 self.dtb.Sync(auto_resize=True)
422 self.assertTrue(dtb2.GetContents() != self.dtb.GetContents())
423
Simon Glassd9dad102019-07-20 12:23:37 -0600424 def testMissingSetInt(self):
425 """Test handling of a missing property with SetInt"""
426 with self.assertRaises(ValueError) as e:
427 self.node.SetInt('one', 1)
428 self.assertIn("node '/spl-test': Missing property 'one'",
429 str(e.exception))
430
431 def testMissingSetData(self):
432 """Test handling of a missing property with SetData"""
433 with self.assertRaises(ValueError) as e:
434 self.node.SetData('one', b'data')
435 self.assertIn("node '/spl-test': Missing property 'one'",
436 str(e.exception))
437
438 def testMissingSetString(self):
439 """Test handling of a missing property with SetString"""
440 with self.assertRaises(ValueError) as e:
441 self.node.SetString('one', 1)
442 self.assertIn("node '/spl-test': Missing property 'one'",
443 str(e.exception))
444
Simon Glass2ba98752018-07-06 10:27:24 -0600445
Simon Glass2a2d91d2018-07-06 10:27:28 -0600446class TestFdtUtil(unittest.TestCase):
447 """Tests for the fdt_util module
448
449 This module will likely be mostly replaced at some point, once upstream
450 libfdt has better Python support. For now, this provides tests for current
451 functionality.
452 """
453 @classmethod
454 def setUpClass(cls):
455 tools.PrepareOutputDir(None)
456
Simon Glasse0e62752018-10-01 21:12:41 -0600457 @classmethod
458 def tearDownClass(cls):
459 tools.FinaliseOutputDir()
460
Simon Glass2a2d91d2018-07-06 10:27:28 -0600461 def setUp(self):
462 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
463 self.node = self.dtb.GetNode('/spl-test')
464
465 def testGetInt(self):
466 self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
467 self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
468
469 with self.assertRaises(ValueError) as e:
470 self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
471 self.assertIn("property 'intarray' has list value: expecting a single "
472 'integer', str(e.exception))
473
474 def testGetString(self):
475 self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
476 self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
477 'test'))
478
479 with self.assertRaises(ValueError) as e:
480 self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
481 self.assertIn("property 'stringarray' has list value: expecting a "
482 'single string', str(e.exception))
483
484 def testGetBool(self):
485 self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
486 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
487 self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
488 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
489
Simon Glass3af8e492018-07-17 13:25:40 -0600490 def testGetByte(self):
491 self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
492 self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
493
494 with self.assertRaises(ValueError) as e:
495 fdt_util.GetByte(self.node, 'longbytearray')
496 self.assertIn("property 'longbytearray' has list value: expecting a "
497 'single byte', str(e.exception))
498
499 with self.assertRaises(ValueError) as e:
500 fdt_util.GetByte(self.node, 'intval')
501 self.assertIn("property 'intval' has length 4, expecting 1",
502 str(e.exception))
503
Simon Glass94a7c602018-07-17 13:25:46 -0600504 def testGetPhandleList(self):
505 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
506 node = dtb.GetNode('/phandle-source2')
507 self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
508 node = dtb.GetNode('/phandle-source')
509 self.assertEqual([1, 2, 11, 3, 12, 13, 1],
510 fdt_util.GetPhandleList(node, 'clocks'))
511 self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
512
Simon Glass53af22a2018-07-17 13:25:32 -0600513 def testGetDataType(self):
514 self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
515 self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
516 str))
517 with self.assertRaises(ValueError) as e:
518 self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
519 bool))
Simon Glass2a2d91d2018-07-06 10:27:28 -0600520 def testFdtCellsToCpu(self):
521 val = self.node.props['intarray'].value
522 self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
523 self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
524
525 dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
Simon Glasse66d3182019-05-17 22:00:40 -0600526 node1 = dtb2.GetNode('/test1')
527 val = node1.props['reg'].value
Simon Glass2a2d91d2018-07-06 10:27:28 -0600528 self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
529
Simon Glasse66d3182019-05-17 22:00:40 -0600530 node2 = dtb2.GetNode('/test2')
531 val = node2.props['reg'].value
532 self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
533 self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
534 2))
535 self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
536
Simon Glass2a2d91d2018-07-06 10:27:28 -0600537 def testEnsureCompiled(self):
538 """Test a degenerate case of this function"""
539 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
540 self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
541
Simon Glass2a2d91d2018-07-06 10:27:28 -0600542
543def RunTestCoverage():
544 """Run the tests and check that we get 100% coverage"""
545 test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
546 ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
547
548
Simon Glass2ba98752018-07-06 10:27:24 -0600549def RunTests(args):
550 """Run all the test we have for the fdt model
551
552 Args:
553 args: List of positional args provided to fdt. This can hold a test
554 name to execute (as in 'fdt -t testFdt', for example)
555 """
556 result = unittest.TestResult()
557 sys.argv = [sys.argv[0]]
558 test_name = args and args[0] or None
Simon Glass2a2d91d2018-07-06 10:27:28 -0600559 for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
Simon Glass2ba98752018-07-06 10:27:24 -0600560 if test_name:
561 try:
562 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
563 except AttributeError:
564 continue
565 else:
566 suite = unittest.TestLoader().loadTestsFromTestCase(module)
567 suite.run(result)
568
Simon Glass90a81322019-05-17 22:00:31 -0600569 print(result)
Simon Glass2ba98752018-07-06 10:27:24 -0600570 for _, err in result.errors:
Simon Glass90a81322019-05-17 22:00:31 -0600571 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600572 for _, err in result.failures:
Simon Glass90a81322019-05-17 22:00:31 -0600573 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600574
575if __name__ != '__main__':
576 sys.exit(1)
577
578parser = OptionParser()
Simon Glass2a2d91d2018-07-06 10:27:28 -0600579parser.add_option('-B', '--build-dir', type='string', default='b',
580 help='Directory containing the build output')
Simon Glass11ae93e2018-10-01 21:12:47 -0600581parser.add_option('-P', '--processes', type=int,
582 help='set number of processes to use for running tests')
Simon Glass2ba98752018-07-06 10:27:24 -0600583parser.add_option('-t', '--test', action='store_true', dest='test',
584 default=False, help='run tests')
Simon Glass2a2d91d2018-07-06 10:27:28 -0600585parser.add_option('-T', '--test-coverage', action='store_true',
586 default=False, help='run tests and check for 100% coverage')
Simon Glass2ba98752018-07-06 10:27:24 -0600587(options, args) = parser.parse_args()
588
589# Run our meagre tests
590if options.test:
591 RunTests(args)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600592elif options.test_coverage:
593 RunTestCoverage()