blob: ed2d982a8fc8bc9c4ec6717a4773834745734259 [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
Simon Glass61b88e52019-05-17 22:00:31 -06007from __future__ import print_function
8
Simon Glass0ed50752018-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 Glass5872f0c2019-05-17 22:00:41 -060022from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
Simon Glass9c526332018-07-06 10:27:28 -060023import fdt_util
Simon Glass0ed50752018-07-06 10:27:24 -060024from fdt_util import fdt32_to_cpu
25import libfdt
26import test_util
27import tools
28
Simon Glass4df8a0c2018-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 Glass1cd40082019-05-17 22:00:36 -060050 return prop, [tools.ToChar(x) for x in data]
Simon Glass4df8a0c2018-07-06 10:27:29 -060051
52
Simon Glass0ed50752018-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 Glass752e7552018-10-01 21:12:41 -060065 tools.FinaliseOutputDir()
Simon Glass0ed50752018-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))
Simon Glass3b9a8292019-07-20 12:23:39 -060080
Simon Glass0ed50752018-07-06 10:27:24 -060081 node = self.dtb.GetNode('/i2c@0/pmic@9')
82 self.assertTrue(isinstance(node, fdt.Node))
83 self.assertEqual('pmic@9', node.name)
Simon Glass9c526332018-07-06 10:27:28 -060084 self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
Simon Glass0ed50752018-07-06 10:27:24 -060085
Simon Glass3b9a8292019-07-20 12:23:39 -060086 node = self.dtb.GetNode('/')
87 self.assertTrue(isinstance(node, fdt.Node))
88 self.assertEqual(0, node.Offset())
89
Simon Glass0ed50752018-07-06 10:27:24 -060090 def testFlush(self):
91 """Check that we can flush the device tree out to its file"""
92 fname = self.dtb._fname
Simon Glass80d54ee2019-05-17 22:00:39 -060093 with open(fname, 'rb') as fd:
Simon Glass0ed50752018-07-06 10:27:24 -060094 data = fd.read()
95 os.remove(fname)
96 with self.assertRaises(IOError):
Simon Glass80d54ee2019-05-17 22:00:39 -060097 open(fname, 'rb')
Simon Glass0ed50752018-07-06 10:27:24 -060098 self.dtb.Flush()
Simon Glass80d54ee2019-05-17 22:00:39 -060099 with open(fname, 'rb') as fd:
Simon Glass0ed50752018-07-06 10:27:24 -0600100 data = fd.read()
101
102 def testPack(self):
103 """Test that packing a device tree works"""
104 self.dtb.Pack()
105
106 def testGetFdt(self):
107 """Tetst that we can access the raw device-tree data"""
Simon Glass792d2392018-07-06 10:27:27 -0600108 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
Simon Glass0ed50752018-07-06 10:27:24 -0600109
110 def testGetProps(self):
111 """Tests obtaining a list of properties"""
112 node = self.dtb.GetNode('/spl-test')
113 props = self.dtb.GetProps(node)
114 self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
Simon Glass9c526332018-07-06 10:27:28 -0600115 'intarray', 'intval', 'longbytearray', 'notstring',
Simon Glass0ed50752018-07-06 10:27:24 -0600116 'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
117 sorted(props.keys()))
118
119 def testCheckError(self):
120 """Tests the ChecKError() function"""
121 with self.assertRaises(ValueError) as e:
Simon Glass9c526332018-07-06 10:27:28 -0600122 fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
Simon Glass0ed50752018-07-06 10:27:24 -0600123 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
124
Simon Glasse2d65282018-07-17 13:25:46 -0600125 def testGetFdt(self):
126 node = self.dtb.GetNode('/spl-test')
127 self.assertEqual(self.dtb, node.GetFdt())
Simon Glass0ed50752018-07-06 10:27:24 -0600128
Simon Glass5872f0c2019-05-17 22:00:41 -0600129 def testBytesToValue(self):
130 self.assertEqual(BytesToValue(b'this\0is\0'),
131 (TYPE_STRING, ['this', 'is']))
132
Simon Glass0ed50752018-07-06 10:27:24 -0600133class TestNode(unittest.TestCase):
134 """Test operation of the Node class"""
135
136 @classmethod
137 def setUpClass(cls):
138 tools.PrepareOutputDir(None)
139
140 @classmethod
141 def tearDownClass(cls):
Simon Glass752e7552018-10-01 21:12:41 -0600142 tools.FinaliseOutputDir()
Simon Glass0ed50752018-07-06 10:27:24 -0600143
144 def setUp(self):
145 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
146 self.node = self.dtb.GetNode('/spl-test')
147
148 def testOffset(self):
149 """Tests that we can obtain the offset of a node"""
150 self.assertTrue(self.node.Offset() > 0)
151
152 def testDelete(self):
153 """Tests that we can delete a property"""
154 node2 = self.dtb.GetNode('/spl-test2')
155 offset1 = node2.Offset()
156 self.node.DeleteProp('intval')
157 offset2 = node2.Offset()
158 self.assertTrue(offset2 < offset1)
159 self.node.DeleteProp('intarray')
160 offset3 = node2.Offset()
161 self.assertTrue(offset3 < offset2)
Simon Glass9c526332018-07-06 10:27:28 -0600162 with self.assertRaises(libfdt.FdtException):
163 self.node.DeleteProp('missing')
Simon Glass0ed50752018-07-06 10:27:24 -0600164
Simon Glass4df8a0c2018-07-06 10:27:29 -0600165 def testDeleteGetOffset(self):
166 """Test that property offset update when properties are deleted"""
167 self.node.DeleteProp('intval')
168 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
169 self.assertEqual(prop.value, value)
170
Simon Glass0ed50752018-07-06 10:27:24 -0600171 def testFindNode(self):
Simon Glassaa1a5d72018-07-17 13:25:41 -0600172 """Tests that we can find a node using the FindNode() functoin"""
173 node = self.dtb.GetRoot().FindNode('i2c@0')
Simon Glass0ed50752018-07-06 10:27:24 -0600174 self.assertEqual('i2c@0', node.name)
Simon Glassaa1a5d72018-07-17 13:25:41 -0600175 subnode = node.FindNode('pmic@9')
Simon Glass0ed50752018-07-06 10:27:24 -0600176 self.assertEqual('pmic@9', subnode.name)
Simon Glassaa1a5d72018-07-17 13:25:41 -0600177 self.assertEqual(None, node.FindNode('missing'))
Simon Glass0ed50752018-07-06 10:27:24 -0600178
Simon Glass4df8a0c2018-07-06 10:27:29 -0600179 def testRefreshMissingNode(self):
180 """Test refreshing offsets when an extra node is present in dtb"""
181 # Delete it from our tables, not the device tree
182 del self.dtb._root.subnodes[-1]
183 with self.assertRaises(ValueError) as e:
184 self.dtb.Refresh()
185 self.assertIn('Internal error, offset', str(e.exception))
186
187 def testRefreshExtraNode(self):
188 """Test refreshing offsets when an expected node is missing"""
189 # Delete it from the device tre, not our tables
190 self.dtb.GetFdtObj().del_node(self.node.Offset())
191 with self.assertRaises(ValueError) as e:
192 self.dtb.Refresh()
193 self.assertIn('Internal error, node name mismatch '
194 'spl-test != spl-test2', str(e.exception))
195
196 def testRefreshMissingProp(self):
197 """Test refreshing offsets when an extra property is present in dtb"""
198 # Delete it from our tables, not the device tree
199 del self.node.props['notstring']
200 with self.assertRaises(ValueError) as e:
201 self.dtb.Refresh()
202 self.assertIn("Internal error, property 'notstring' missing, offset ",
203 str(e.exception))
204
Simon Glasse2d65282018-07-17 13:25:46 -0600205 def testLookupPhandle(self):
206 """Test looking up a single phandle"""
207 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
208 node = dtb.GetNode('/phandle-source2')
209 prop = node.props['clocks']
210 target = dtb.GetNode('/phandle-target')
211 self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
212
Simon Glass0ed50752018-07-06 10:27:24 -0600213
214class TestProp(unittest.TestCase):
215 """Test operation of the Prop class"""
216
217 @classmethod
218 def setUpClass(cls):
219 tools.PrepareOutputDir(None)
220
221 @classmethod
222 def tearDownClass(cls):
Simon Glass752e7552018-10-01 21:12:41 -0600223 tools.FinaliseOutputDir()
Simon Glass0ed50752018-07-06 10:27:24 -0600224
225 def setUp(self):
226 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
227 self.node = self.dtb.GetNode('/spl-test')
228 self.fdt = self.dtb.GetFdtObj()
229
Simon Glassc5eddc82018-07-06 10:27:30 -0600230 def testMissingNode(self):
231 self.assertEqual(None, self.dtb.GetNode('missing'))
232
Simon Glass9c526332018-07-06 10:27:28 -0600233 def testPhandle(self):
234 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
Simon Glass609e2b12018-07-06 10:27:31 -0600235 node = dtb.GetNode('/phandle-source2')
236 prop = node.props['clocks']
237 self.assertTrue(fdt32_to_cpu(prop.value) > 0)
Simon Glass9c526332018-07-06 10:27:28 -0600238
239 def _ConvertProp(self, prop_name):
240 """Helper function to look up a property in self.node and return it
241
242 Args:
243 Property name to find
244
245 Return fdt.Prop object for this property
246 """
Simon Glassb474c762018-07-26 14:02:13 -0600247 p = self.fdt.getprop(self.node.Offset(), prop_name)
Simon Glass9c526332018-07-06 10:27:28 -0600248 return fdt.Prop(self.node, -1, prop_name, p)
249
250 def testMakeProp(self):
251 """Test we can convert all the the types that are supported"""
252 prop = self._ConvertProp('boolval')
253 self.assertEqual(fdt.TYPE_BOOL, prop.type)
254 self.assertEqual(True, prop.value)
255
256 prop = self._ConvertProp('intval')
257 self.assertEqual(fdt.TYPE_INT, prop.type)
258 self.assertEqual(1, fdt32_to_cpu(prop.value))
259
260 prop = self._ConvertProp('intarray')
261 self.assertEqual(fdt.TYPE_INT, prop.type)
262 val = [fdt32_to_cpu(val) for val in prop.value]
263 self.assertEqual([2, 3, 4], val)
264
265 prop = self._ConvertProp('byteval')
266 self.assertEqual(fdt.TYPE_BYTE, prop.type)
267 self.assertEqual(5, ord(prop.value))
268
269 prop = self._ConvertProp('longbytearray')
270 self.assertEqual(fdt.TYPE_BYTE, prop.type)
271 val = [ord(val) for val in prop.value]
272 self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
273
274 prop = self._ConvertProp('stringval')
275 self.assertEqual(fdt.TYPE_STRING, prop.type)
276 self.assertEqual('message', prop.value)
277
278 prop = self._ConvertProp('stringarray')
279 self.assertEqual(fdt.TYPE_STRING, prop.type)
280 self.assertEqual(['multi-word', 'message'], prop.value)
281
282 prop = self._ConvertProp('notstring')
283 self.assertEqual(fdt.TYPE_BYTE, prop.type)
284 val = [ord(val) for val in prop.value]
285 self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
286
Simon Glass0ed50752018-07-06 10:27:24 -0600287 def testGetEmpty(self):
288 """Tests the GetEmpty() function for the various supported types"""
289 self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
290 self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
Simon Glass6bbfafb2019-05-17 22:00:33 -0600291 self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
Simon Glass0ed50752018-07-06 10:27:24 -0600292 self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
293
294 def testGetOffset(self):
295 """Test we can get the offset of a property"""
Simon Glass4df8a0c2018-07-06 10:27:29 -0600296 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
297 self.assertEqual(prop.value, value)
Simon Glass0ed50752018-07-06 10:27:24 -0600298
299 def testWiden(self):
300 """Test widening of values"""
301 node2 = self.dtb.GetNode('/spl-test2')
302 prop = self.node.props['intval']
303
304 # No action
305 prop2 = node2.props['intval']
306 prop.Widen(prop2)
307 self.assertEqual(fdt.TYPE_INT, prop.type)
308 self.assertEqual(1, fdt32_to_cpu(prop.value))
309
310 # Convert singla value to array
311 prop2 = self.node.props['intarray']
312 prop.Widen(prop2)
313 self.assertEqual(fdt.TYPE_INT, prop.type)
314 self.assertTrue(isinstance(prop.value, list))
315
316 # A 4-byte array looks like a single integer. When widened by a longer
317 # byte array, it should turn into an array.
318 prop = self.node.props['longbytearray']
319 prop2 = node2.props['longbytearray']
320 self.assertFalse(isinstance(prop2.value, list))
321 self.assertEqual(4, len(prop2.value))
322 prop2.Widen(prop)
323 self.assertTrue(isinstance(prop2.value, list))
324 self.assertEqual(9, len(prop2.value))
325
326 # Similarly for a string array
327 prop = self.node.props['stringval']
328 prop2 = node2.props['stringarray']
329 self.assertFalse(isinstance(prop.value, list))
330 self.assertEqual(7, len(prop.value))
331 prop.Widen(prop2)
332 self.assertTrue(isinstance(prop.value, list))
333 self.assertEqual(3, len(prop.value))
334
335 # Enlarging an existing array
336 prop = self.node.props['stringarray']
337 prop2 = node2.props['stringarray']
338 self.assertTrue(isinstance(prop.value, list))
339 self.assertEqual(2, len(prop.value))
340 prop.Widen(prop2)
341 self.assertTrue(isinstance(prop.value, list))
342 self.assertEqual(3, len(prop.value))
343
Simon Glasse80c5562018-07-06 10:27:38 -0600344 def testAdd(self):
345 """Test adding properties"""
346 self.fdt.pack()
347 # This function should automatically expand the device tree
348 self.node.AddZeroProp('one')
349 self.node.AddZeroProp('two')
350 self.node.AddZeroProp('three')
Simon Glasseddd7292018-09-14 04:57:13 -0600351 self.dtb.Sync(auto_resize=True)
Simon Glasse80c5562018-07-06 10:27:38 -0600352
353 # Updating existing properties should be OK, since the device-tree size
354 # does not change
355 self.fdt.pack()
356 self.node.SetInt('one', 1)
357 self.node.SetInt('two', 2)
358 self.node.SetInt('three', 3)
Simon Glasseddd7292018-09-14 04:57:13 -0600359 self.dtb.Sync(auto_resize=False)
Simon Glasse80c5562018-07-06 10:27:38 -0600360
361 # This should fail since it would need to increase the device-tree size
Simon Glasseddd7292018-09-14 04:57:13 -0600362 self.node.AddZeroProp('four')
Simon Glasse80c5562018-07-06 10:27:38 -0600363 with self.assertRaises(libfdt.FdtException) as e:
Simon Glasseddd7292018-09-14 04:57:13 -0600364 self.dtb.Sync(auto_resize=False)
Simon Glasse80c5562018-07-06 10:27:38 -0600365 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
Simon Glassccd25262018-09-14 04:57:16 -0600366 self.dtb.Sync(auto_resize=True)
Simon Glasse80c5562018-07-06 10:27:38 -0600367
Simon Glasseddd7292018-09-14 04:57:13 -0600368 def testAddNode(self):
369 self.fdt.pack()
Simon Glassf3a17962018-09-14 04:57:15 -0600370 self.node.AddSubnode('subnode')
371 with self.assertRaises(libfdt.FdtException) as e:
372 self.dtb.Sync(auto_resize=False)
373 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
374
375 self.dtb.Sync(auto_resize=True)
376 offset = self.fdt.path_offset('/spl-test/subnode')
377 self.assertTrue(offset > 0)
Simon Glasseddd7292018-09-14 04:57:13 -0600378
Simon Glassccd25262018-09-14 04:57:16 -0600379 def testAddMore(self):
380 """Test various other methods for adding and setting properties"""
381 self.node.AddZeroProp('one')
382 self.dtb.Sync(auto_resize=True)
383 data = self.fdt.getprop(self.node.Offset(), 'one')
384 self.assertEqual(0, fdt32_to_cpu(data))
385
386 self.node.SetInt('one', 1)
387 self.dtb.Sync(auto_resize=False)
388 data = self.fdt.getprop(self.node.Offset(), 'one')
389 self.assertEqual(1, fdt32_to_cpu(data))
390
391 val = '123' + chr(0) + '456'
392 self.node.AddString('string', val)
393 self.dtb.Sync(auto_resize=True)
394 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glass1cd40082019-05-17 22:00:36 -0600395 self.assertEqual(tools.ToBytes(val) + b'\0', data)
Simon Glassccd25262018-09-14 04:57:16 -0600396
397 self.fdt.pack()
398 self.node.SetString('string', val + 'x')
399 with self.assertRaises(libfdt.FdtException) as e:
400 self.dtb.Sync(auto_resize=False)
401 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
402 self.node.SetString('string', val[:-1])
403
404 prop = self.node.props['string']
Simon Glass1cd40082019-05-17 22:00:36 -0600405 prop.SetData(tools.ToBytes(val))
Simon Glassccd25262018-09-14 04:57:16 -0600406 self.dtb.Sync(auto_resize=False)
407 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glass1cd40082019-05-17 22:00:36 -0600408 self.assertEqual(tools.ToBytes(val), data)
Simon Glassccd25262018-09-14 04:57:16 -0600409
410 self.node.AddEmptyProp('empty', 5)
411 self.dtb.Sync(auto_resize=True)
412 prop = self.node.props['empty']
Simon Glass1cd40082019-05-17 22:00:36 -0600413 prop.SetData(tools.ToBytes(val))
Simon Glassccd25262018-09-14 04:57:16 -0600414 self.dtb.Sync(auto_resize=False)
415 data = self.fdt.getprop(self.node.Offset(), 'empty')
Simon Glass1cd40082019-05-17 22:00:36 -0600416 self.assertEqual(tools.ToBytes(val), data)
Simon Glassccd25262018-09-14 04:57:16 -0600417
Simon Glass1cd40082019-05-17 22:00:36 -0600418 self.node.SetData('empty', b'123')
419 self.assertEqual(b'123', prop.bytes)
Simon Glassccd25262018-09-14 04:57:16 -0600420
Simon Glassb8a49292018-09-14 04:57:17 -0600421 def testFromData(self):
422 dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
423 self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
424
425 self.node.AddEmptyProp('empty', 5)
426 self.dtb.Sync(auto_resize=True)
427 self.assertTrue(dtb2.GetContents() != self.dtb.GetContents())
428
Simon Glassa683a5f2019-07-20 12:23:37 -0600429 def testMissingSetInt(self):
430 """Test handling of a missing property with SetInt"""
431 with self.assertRaises(ValueError) as e:
432 self.node.SetInt('one', 1)
433 self.assertIn("node '/spl-test': Missing property 'one'",
434 str(e.exception))
435
436 def testMissingSetData(self):
437 """Test handling of a missing property with SetData"""
438 with self.assertRaises(ValueError) as e:
439 self.node.SetData('one', b'data')
440 self.assertIn("node '/spl-test': Missing property 'one'",
441 str(e.exception))
442
443 def testMissingSetString(self):
444 """Test handling of a missing property with SetString"""
445 with self.assertRaises(ValueError) as e:
446 self.node.SetString('one', 1)
447 self.assertIn("node '/spl-test': Missing property 'one'",
448 str(e.exception))
449
Simon Glass0ed50752018-07-06 10:27:24 -0600450
Simon Glass9c526332018-07-06 10:27:28 -0600451class TestFdtUtil(unittest.TestCase):
452 """Tests for the fdt_util module
453
454 This module will likely be mostly replaced at some point, once upstream
455 libfdt has better Python support. For now, this provides tests for current
456 functionality.
457 """
458 @classmethod
459 def setUpClass(cls):
460 tools.PrepareOutputDir(None)
461
Simon Glass752e7552018-10-01 21:12:41 -0600462 @classmethod
463 def tearDownClass(cls):
464 tools.FinaliseOutputDir()
465
Simon Glass9c526332018-07-06 10:27:28 -0600466 def setUp(self):
467 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
468 self.node = self.dtb.GetNode('/spl-test')
469
470 def testGetInt(self):
471 self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
472 self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
473
474 with self.assertRaises(ValueError) as e:
475 self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
476 self.assertIn("property 'intarray' has list value: expecting a single "
477 'integer', str(e.exception))
478
479 def testGetString(self):
480 self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
481 self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
482 'test'))
483
484 with self.assertRaises(ValueError) as e:
485 self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
486 self.assertIn("property 'stringarray' has list value: expecting a "
487 'single string', str(e.exception))
488
489 def testGetBool(self):
490 self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
491 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
492 self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
493 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
494
Simon Glass53f53992018-07-17 13:25:40 -0600495 def testGetByte(self):
496 self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
497 self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
498
499 with self.assertRaises(ValueError) as e:
500 fdt_util.GetByte(self.node, 'longbytearray')
501 self.assertIn("property 'longbytearray' has list value: expecting a "
502 'single byte', str(e.exception))
503
504 with self.assertRaises(ValueError) as e:
505 fdt_util.GetByte(self.node, 'intval')
506 self.assertIn("property 'intval' has length 4, expecting 1",
507 str(e.exception))
508
Simon Glasse2d65282018-07-17 13:25:46 -0600509 def testGetPhandleList(self):
510 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
511 node = dtb.GetNode('/phandle-source2')
512 self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
513 node = dtb.GetNode('/phandle-source')
514 self.assertEqual([1, 2, 11, 3, 12, 13, 1],
515 fdt_util.GetPhandleList(node, 'clocks'))
516 self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
517
Simon Glass91710b32018-07-17 13:25:32 -0600518 def testGetDataType(self):
519 self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
520 self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
521 str))
522 with self.assertRaises(ValueError) as e:
523 self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
524 bool))
Simon Glass9c526332018-07-06 10:27:28 -0600525 def testFdtCellsToCpu(self):
526 val = self.node.props['intarray'].value
527 self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
528 self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
529
530 dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
Simon Glassb0a34a42019-05-17 22:00:40 -0600531 node1 = dtb2.GetNode('/test1')
532 val = node1.props['reg'].value
Simon Glass9c526332018-07-06 10:27:28 -0600533 self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
534
Simon Glassb0a34a42019-05-17 22:00:40 -0600535 node2 = dtb2.GetNode('/test2')
536 val = node2.props['reg'].value
537 self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
538 self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
539 2))
540 self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
541
Simon Glass9c526332018-07-06 10:27:28 -0600542 def testEnsureCompiled(self):
543 """Test a degenerate case of this function"""
544 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
545 self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
546
Simon Glass9c526332018-07-06 10:27:28 -0600547
548def RunTestCoverage():
549 """Run the tests and check that we get 100% coverage"""
550 test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
551 ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
552
553
Simon Glass0ed50752018-07-06 10:27:24 -0600554def RunTests(args):
555 """Run all the test we have for the fdt model
556
557 Args:
558 args: List of positional args provided to fdt. This can hold a test
559 name to execute (as in 'fdt -t testFdt', for example)
560 """
561 result = unittest.TestResult()
562 sys.argv = [sys.argv[0]]
563 test_name = args and args[0] or None
Simon Glass9c526332018-07-06 10:27:28 -0600564 for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
Simon Glass0ed50752018-07-06 10:27:24 -0600565 if test_name:
566 try:
567 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
568 except AttributeError:
569 continue
570 else:
571 suite = unittest.TestLoader().loadTestsFromTestCase(module)
572 suite.run(result)
573
Simon Glass61b88e52019-05-17 22:00:31 -0600574 print(result)
Simon Glass0ed50752018-07-06 10:27:24 -0600575 for _, err in result.errors:
Simon Glass61b88e52019-05-17 22:00:31 -0600576 print(err)
Simon Glass0ed50752018-07-06 10:27:24 -0600577 for _, err in result.failures:
Simon Glass61b88e52019-05-17 22:00:31 -0600578 print(err)
Simon Glass0ed50752018-07-06 10:27:24 -0600579
580if __name__ != '__main__':
581 sys.exit(1)
582
583parser = OptionParser()
Simon Glass9c526332018-07-06 10:27:28 -0600584parser.add_option('-B', '--build-dir', type='string', default='b',
585 help='Directory containing the build output')
Simon Glass7057d022018-10-01 21:12:47 -0600586parser.add_option('-P', '--processes', type=int,
587 help='set number of processes to use for running tests')
Simon Glass0ed50752018-07-06 10:27:24 -0600588parser.add_option('-t', '--test', action='store_true', dest='test',
589 default=False, help='run tests')
Simon Glass9c526332018-07-06 10:27:28 -0600590parser.add_option('-T', '--test-coverage', action='store_true',
591 default=False, help='run tests and check for 100% coverage')
Simon Glass0ed50752018-07-06 10:27:24 -0600592(options, args) = parser.parse_args()
593
594# Run our meagre tests
595if options.test:
596 RunTests(args)
Simon Glass9c526332018-07-06 10:27:28 -0600597elif options.test_coverage:
598 RunTestCoverage()