blob: 16a4430892e56532e509262b712ac84e9137268f [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
Simon Glassa004f292019-07-20 12:23:49 -060012import shutil
Simon Glass2ba98752018-07-06 10:27:24 -060013import sys
Simon Glassa004f292019-07-20 12:23:49 -060014import tempfile
Simon Glass2ba98752018-07-06 10:27:24 -060015import unittest
16
17# Bring in the patman libraries
18our_path = os.path.dirname(os.path.realpath(__file__))
19for dirname in ['../patman', '..']:
20 sys.path.insert(0, os.path.join(our_path, dirname))
21
22import command
23import fdt
Simon Glassb5f0daf2019-05-17 22:00:41 -060024from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
Simon Glass2a2d91d2018-07-06 10:27:28 -060025import fdt_util
Simon Glass2ba98752018-07-06 10:27:24 -060026from fdt_util import fdt32_to_cpu
27import libfdt
28import test_util
29import tools
30
Simon Glassf9b88b32018-07-06 10:27:29 -060031def _GetPropertyValue(dtb, node, prop_name):
32 """Low-level function to get the property value based on its offset
33
34 This looks directly in the device tree at the property's offset to find
35 its value. It is useful as a check that the property is in the correct
36 place.
37
38 Args:
39 node: Node to look in
40 prop_name: Property name to find
41
42 Returns:
43 Tuple:
44 Prop object found
45 Value of property as a string (found using property offset)
46 """
47 prop = node.props[prop_name]
48
49 # Add 12, which is sizeof(struct fdt_property), to get to start of data
50 offset = prop.GetOffset() + 12
51 data = dtb.GetContents()[offset:offset + len(prop.value)]
Simon Glassf6b64812019-05-17 22:00:36 -060052 return prop, [tools.ToChar(x) for x in data]
Simon Glassf9b88b32018-07-06 10:27:29 -060053
54
Simon Glass2ba98752018-07-06 10:27:24 -060055class TestFdt(unittest.TestCase):
56 """Tests for the Fdt module
57
58 This includes unit tests for some functions and functional tests for the fdt
59 module.
60 """
61 @classmethod
62 def setUpClass(cls):
63 tools.PrepareOutputDir(None)
64
65 @classmethod
66 def tearDownClass(cls):
Simon Glasse0e62752018-10-01 21:12:41 -060067 tools.FinaliseOutputDir()
Simon Glass2ba98752018-07-06 10:27:24 -060068
69 def setUp(self):
70 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
71
72 def testFdt(self):
73 """Test that we can open an Fdt"""
74 self.dtb.Scan()
75 root = self.dtb.GetRoot()
76 self.assertTrue(isinstance(root, fdt.Node))
77
78 def testGetNode(self):
79 """Test the GetNode() method"""
80 node = self.dtb.GetNode('/spl-test')
81 self.assertTrue(isinstance(node, fdt.Node))
Simon Glasse44bc832019-07-20 12:23:39 -060082
Simon Glass2ba98752018-07-06 10:27:24 -060083 node = self.dtb.GetNode('/i2c@0/pmic@9')
84 self.assertTrue(isinstance(node, fdt.Node))
85 self.assertEqual('pmic@9', node.name)
Simon Glass2a2d91d2018-07-06 10:27:28 -060086 self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
Simon Glass2ba98752018-07-06 10:27:24 -060087
Simon Glasse44bc832019-07-20 12:23:39 -060088 node = self.dtb.GetNode('/')
89 self.assertTrue(isinstance(node, fdt.Node))
90 self.assertEqual(0, node.Offset())
91
Simon Glass2ba98752018-07-06 10:27:24 -060092 def testFlush(self):
93 """Check that we can flush the device tree out to its file"""
94 fname = self.dtb._fname
Simon Glass2ab6e132019-05-17 22:00:39 -060095 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-07-06 10:27:24 -060096 data = fd.read()
97 os.remove(fname)
98 with self.assertRaises(IOError):
Simon Glass2ab6e132019-05-17 22:00:39 -060099 open(fname, 'rb')
Simon Glass2ba98752018-07-06 10:27:24 -0600100 self.dtb.Flush()
Simon Glass2ab6e132019-05-17 22:00:39 -0600101 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-07-06 10:27:24 -0600102 data = fd.read()
103
104 def testPack(self):
105 """Test that packing a device tree works"""
106 self.dtb.Pack()
107
108 def testGetFdt(self):
109 """Tetst that we can access the raw device-tree data"""
Simon Glass96066242018-07-06 10:27:27 -0600110 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
Simon Glass2ba98752018-07-06 10:27:24 -0600111
112 def testGetProps(self):
113 """Tests obtaining a list of properties"""
114 node = self.dtb.GetNode('/spl-test')
115 props = self.dtb.GetProps(node)
116 self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
Simon Glass2a2d91d2018-07-06 10:27:28 -0600117 'intarray', 'intval', 'longbytearray', 'notstring',
Simon Glass2ba98752018-07-06 10:27:24 -0600118 'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
119 sorted(props.keys()))
120
121 def testCheckError(self):
122 """Tests the ChecKError() function"""
123 with self.assertRaises(ValueError) as e:
Simon Glass2a2d91d2018-07-06 10:27:28 -0600124 fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
Simon Glass2ba98752018-07-06 10:27:24 -0600125 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
126
Simon Glass94a7c602018-07-17 13:25:46 -0600127 def testGetFdt(self):
128 node = self.dtb.GetNode('/spl-test')
129 self.assertEqual(self.dtb, node.GetFdt())
Simon Glass2ba98752018-07-06 10:27:24 -0600130
Simon Glassb5f0daf2019-05-17 22:00:41 -0600131 def testBytesToValue(self):
132 self.assertEqual(BytesToValue(b'this\0is\0'),
133 (TYPE_STRING, ['this', 'is']))
134
Simon Glass2ba98752018-07-06 10:27:24 -0600135class TestNode(unittest.TestCase):
136 """Test operation of the Node class"""
137
138 @classmethod
139 def setUpClass(cls):
140 tools.PrepareOutputDir(None)
141
142 @classmethod
143 def tearDownClass(cls):
Simon Glasse0e62752018-10-01 21:12:41 -0600144 tools.FinaliseOutputDir()
Simon Glass2ba98752018-07-06 10:27:24 -0600145
146 def setUp(self):
147 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
148 self.node = self.dtb.GetNode('/spl-test')
149
150 def testOffset(self):
151 """Tests that we can obtain the offset of a node"""
152 self.assertTrue(self.node.Offset() > 0)
153
154 def testDelete(self):
155 """Tests that we can delete a property"""
156 node2 = self.dtb.GetNode('/spl-test2')
157 offset1 = node2.Offset()
158 self.node.DeleteProp('intval')
159 offset2 = node2.Offset()
160 self.assertTrue(offset2 < offset1)
161 self.node.DeleteProp('intarray')
162 offset3 = node2.Offset()
163 self.assertTrue(offset3 < offset2)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600164 with self.assertRaises(libfdt.FdtException):
165 self.node.DeleteProp('missing')
Simon Glass2ba98752018-07-06 10:27:24 -0600166
Simon Glassf9b88b32018-07-06 10:27:29 -0600167 def testDeleteGetOffset(self):
168 """Test that property offset update when properties are deleted"""
169 self.node.DeleteProp('intval')
170 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
171 self.assertEqual(prop.value, value)
172
Simon Glass2ba98752018-07-06 10:27:24 -0600173 def testFindNode(self):
Simon Glass1d858882018-07-17 13:25:41 -0600174 """Tests that we can find a node using the FindNode() functoin"""
175 node = self.dtb.GetRoot().FindNode('i2c@0')
Simon Glass2ba98752018-07-06 10:27:24 -0600176 self.assertEqual('i2c@0', node.name)
Simon Glass1d858882018-07-17 13:25:41 -0600177 subnode = node.FindNode('pmic@9')
Simon Glass2ba98752018-07-06 10:27:24 -0600178 self.assertEqual('pmic@9', subnode.name)
Simon Glass1d858882018-07-17 13:25:41 -0600179 self.assertEqual(None, node.FindNode('missing'))
Simon Glass2ba98752018-07-06 10:27:24 -0600180
Simon Glassf9b88b32018-07-06 10:27:29 -0600181 def testRefreshMissingNode(self):
182 """Test refreshing offsets when an extra node is present in dtb"""
183 # Delete it from our tables, not the device tree
184 del self.dtb._root.subnodes[-1]
185 with self.assertRaises(ValueError) as e:
186 self.dtb.Refresh()
187 self.assertIn('Internal error, offset', str(e.exception))
188
189 def testRefreshExtraNode(self):
190 """Test refreshing offsets when an expected node is missing"""
191 # Delete it from the device tre, not our tables
192 self.dtb.GetFdtObj().del_node(self.node.Offset())
193 with self.assertRaises(ValueError) as e:
194 self.dtb.Refresh()
195 self.assertIn('Internal error, node name mismatch '
196 'spl-test != spl-test2', str(e.exception))
197
198 def testRefreshMissingProp(self):
199 """Test refreshing offsets when an extra property is present in dtb"""
200 # Delete it from our tables, not the device tree
201 del self.node.props['notstring']
202 with self.assertRaises(ValueError) as e:
203 self.dtb.Refresh()
204 self.assertIn("Internal error, property 'notstring' missing, offset ",
205 str(e.exception))
206
Simon Glass94a7c602018-07-17 13:25:46 -0600207 def testLookupPhandle(self):
208 """Test looking up a single phandle"""
209 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
210 node = dtb.GetNode('/phandle-source2')
211 prop = node.props['clocks']
212 target = dtb.GetNode('/phandle-target')
213 self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
214
Simon Glass2ba98752018-07-06 10:27:24 -0600215
216class TestProp(unittest.TestCase):
217 """Test operation of the Prop class"""
218
219 @classmethod
220 def setUpClass(cls):
221 tools.PrepareOutputDir(None)
222
223 @classmethod
224 def tearDownClass(cls):
Simon Glasse0e62752018-10-01 21:12:41 -0600225 tools.FinaliseOutputDir()
Simon Glass2ba98752018-07-06 10:27:24 -0600226
227 def setUp(self):
228 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
229 self.node = self.dtb.GetNode('/spl-test')
230 self.fdt = self.dtb.GetFdtObj()
231
Simon Glassb9066ff2018-07-06 10:27:30 -0600232 def testMissingNode(self):
233 self.assertEqual(None, self.dtb.GetNode('missing'))
234
Simon Glass2a2d91d2018-07-06 10:27:28 -0600235 def testPhandle(self):
236 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
Simon Glass760b7172018-07-06 10:27:31 -0600237 node = dtb.GetNode('/phandle-source2')
238 prop = node.props['clocks']
239 self.assertTrue(fdt32_to_cpu(prop.value) > 0)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600240
241 def _ConvertProp(self, prop_name):
242 """Helper function to look up a property in self.node and return it
243
244 Args:
245 Property name to find
246
247 Return fdt.Prop object for this property
248 """
Simon Glass50c59522018-07-26 14:02:13 -0600249 p = self.fdt.getprop(self.node.Offset(), prop_name)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600250 return fdt.Prop(self.node, -1, prop_name, p)
251
252 def testMakeProp(self):
253 """Test we can convert all the the types that are supported"""
254 prop = self._ConvertProp('boolval')
255 self.assertEqual(fdt.TYPE_BOOL, prop.type)
256 self.assertEqual(True, prop.value)
257
258 prop = self._ConvertProp('intval')
259 self.assertEqual(fdt.TYPE_INT, prop.type)
260 self.assertEqual(1, fdt32_to_cpu(prop.value))
261
262 prop = self._ConvertProp('intarray')
263 self.assertEqual(fdt.TYPE_INT, prop.type)
264 val = [fdt32_to_cpu(val) for val in prop.value]
265 self.assertEqual([2, 3, 4], val)
266
267 prop = self._ConvertProp('byteval')
268 self.assertEqual(fdt.TYPE_BYTE, prop.type)
269 self.assertEqual(5, ord(prop.value))
270
271 prop = self._ConvertProp('longbytearray')
272 self.assertEqual(fdt.TYPE_BYTE, prop.type)
273 val = [ord(val) for val in prop.value]
274 self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
275
276 prop = self._ConvertProp('stringval')
277 self.assertEqual(fdt.TYPE_STRING, prop.type)
278 self.assertEqual('message', prop.value)
279
280 prop = self._ConvertProp('stringarray')
281 self.assertEqual(fdt.TYPE_STRING, prop.type)
282 self.assertEqual(['multi-word', 'message'], prop.value)
283
284 prop = self._ConvertProp('notstring')
285 self.assertEqual(fdt.TYPE_BYTE, prop.type)
286 val = [ord(val) for val in prop.value]
287 self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
288
Simon Glass2ba98752018-07-06 10:27:24 -0600289 def testGetEmpty(self):
290 """Tests the GetEmpty() function for the various supported types"""
291 self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
292 self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
Simon Glass194b8d52019-05-17 22:00:33 -0600293 self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
Simon Glass2ba98752018-07-06 10:27:24 -0600294 self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
295
296 def testGetOffset(self):
297 """Test we can get the offset of a property"""
Simon Glassf9b88b32018-07-06 10:27:29 -0600298 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
299 self.assertEqual(prop.value, value)
Simon Glass2ba98752018-07-06 10:27:24 -0600300
301 def testWiden(self):
302 """Test widening of values"""
303 node2 = self.dtb.GetNode('/spl-test2')
304 prop = self.node.props['intval']
305
306 # No action
307 prop2 = node2.props['intval']
308 prop.Widen(prop2)
309 self.assertEqual(fdt.TYPE_INT, prop.type)
310 self.assertEqual(1, fdt32_to_cpu(prop.value))
311
312 # Convert singla value to array
313 prop2 = self.node.props['intarray']
314 prop.Widen(prop2)
315 self.assertEqual(fdt.TYPE_INT, prop.type)
316 self.assertTrue(isinstance(prop.value, list))
317
318 # A 4-byte array looks like a single integer. When widened by a longer
319 # byte array, it should turn into an array.
320 prop = self.node.props['longbytearray']
321 prop2 = node2.props['longbytearray']
322 self.assertFalse(isinstance(prop2.value, list))
323 self.assertEqual(4, len(prop2.value))
324 prop2.Widen(prop)
325 self.assertTrue(isinstance(prop2.value, list))
326 self.assertEqual(9, len(prop2.value))
327
328 # Similarly for a string array
329 prop = self.node.props['stringval']
330 prop2 = node2.props['stringarray']
331 self.assertFalse(isinstance(prop.value, list))
332 self.assertEqual(7, len(prop.value))
333 prop.Widen(prop2)
334 self.assertTrue(isinstance(prop.value, list))
335 self.assertEqual(3, len(prop.value))
336
337 # Enlarging an existing array
338 prop = self.node.props['stringarray']
339 prop2 = node2.props['stringarray']
340 self.assertTrue(isinstance(prop.value, list))
341 self.assertEqual(2, len(prop.value))
342 prop.Widen(prop2)
343 self.assertTrue(isinstance(prop.value, list))
344 self.assertEqual(3, len(prop.value))
345
Simon Glass116adec2018-07-06 10:27:38 -0600346 def testAdd(self):
347 """Test adding properties"""
348 self.fdt.pack()
349 # This function should automatically expand the device tree
350 self.node.AddZeroProp('one')
351 self.node.AddZeroProp('two')
352 self.node.AddZeroProp('three')
Simon Glassfa80c252018-09-14 04:57:13 -0600353 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-07-06 10:27:38 -0600354
355 # Updating existing properties should be OK, since the device-tree size
356 # does not change
357 self.fdt.pack()
358 self.node.SetInt('one', 1)
359 self.node.SetInt('two', 2)
360 self.node.SetInt('three', 3)
Simon Glassfa80c252018-09-14 04:57:13 -0600361 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600362
363 # This should fail since it would need to increase the device-tree size
Simon Glassfa80c252018-09-14 04:57:13 -0600364 self.node.AddZeroProp('four')
Simon Glass116adec2018-07-06 10:27:38 -0600365 with self.assertRaises(libfdt.FdtException) as e:
Simon Glassfa80c252018-09-14 04:57:13 -0600366 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600367 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
Simon Glass64349612018-09-14 04:57:16 -0600368 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-07-06 10:27:38 -0600369
Simon Glassfa80c252018-09-14 04:57:13 -0600370 def testAddNode(self):
371 self.fdt.pack()
Simon Glasse21c27a2018-09-14 04:57:15 -0600372 self.node.AddSubnode('subnode')
373 with self.assertRaises(libfdt.FdtException) as e:
374 self.dtb.Sync(auto_resize=False)
375 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
376
377 self.dtb.Sync(auto_resize=True)
378 offset = self.fdt.path_offset('/spl-test/subnode')
379 self.assertTrue(offset > 0)
Simon Glassfa80c252018-09-14 04:57:13 -0600380
Simon Glass64349612018-09-14 04:57:16 -0600381 def testAddMore(self):
382 """Test various other methods for adding and setting properties"""
383 self.node.AddZeroProp('one')
384 self.dtb.Sync(auto_resize=True)
385 data = self.fdt.getprop(self.node.Offset(), 'one')
386 self.assertEqual(0, fdt32_to_cpu(data))
387
388 self.node.SetInt('one', 1)
389 self.dtb.Sync(auto_resize=False)
390 data = self.fdt.getprop(self.node.Offset(), 'one')
391 self.assertEqual(1, fdt32_to_cpu(data))
392
393 val = '123' + chr(0) + '456'
394 self.node.AddString('string', val)
395 self.dtb.Sync(auto_resize=True)
396 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glassf6b64812019-05-17 22:00:36 -0600397 self.assertEqual(tools.ToBytes(val) + b'\0', data)
Simon Glass64349612018-09-14 04:57:16 -0600398
399 self.fdt.pack()
400 self.node.SetString('string', val + 'x')
401 with self.assertRaises(libfdt.FdtException) as e:
402 self.dtb.Sync(auto_resize=False)
403 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
404 self.node.SetString('string', val[:-1])
405
406 prop = self.node.props['string']
Simon Glassf6b64812019-05-17 22:00:36 -0600407 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600408 self.dtb.Sync(auto_resize=False)
409 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glassf6b64812019-05-17 22:00:36 -0600410 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-09-14 04:57:16 -0600411
412 self.node.AddEmptyProp('empty', 5)
413 self.dtb.Sync(auto_resize=True)
414 prop = self.node.props['empty']
Simon Glassf6b64812019-05-17 22:00:36 -0600415 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600416 self.dtb.Sync(auto_resize=False)
417 data = self.fdt.getprop(self.node.Offset(), 'empty')
Simon Glassf6b64812019-05-17 22:00:36 -0600418 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-09-14 04:57:16 -0600419
Simon Glassf6b64812019-05-17 22:00:36 -0600420 self.node.SetData('empty', b'123')
421 self.assertEqual(b'123', prop.bytes)
Simon Glass64349612018-09-14 04:57:16 -0600422
Simon Glass746aee32018-09-14 04:57:17 -0600423 def testFromData(self):
424 dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
425 self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
426
427 self.node.AddEmptyProp('empty', 5)
428 self.dtb.Sync(auto_resize=True)
429 self.assertTrue(dtb2.GetContents() != self.dtb.GetContents())
430
Simon Glassd9dad102019-07-20 12:23:37 -0600431 def testMissingSetInt(self):
432 """Test handling of a missing property with SetInt"""
433 with self.assertRaises(ValueError) as e:
434 self.node.SetInt('one', 1)
435 self.assertIn("node '/spl-test': Missing property 'one'",
436 str(e.exception))
437
438 def testMissingSetData(self):
439 """Test handling of a missing property with SetData"""
440 with self.assertRaises(ValueError) as e:
441 self.node.SetData('one', b'data')
442 self.assertIn("node '/spl-test': Missing property 'one'",
443 str(e.exception))
444
445 def testMissingSetString(self):
446 """Test handling of a missing property with SetString"""
447 with self.assertRaises(ValueError) as e:
448 self.node.SetString('one', 1)
449 self.assertIn("node '/spl-test': Missing property 'one'",
450 str(e.exception))
451
Simon Glass2ba98752018-07-06 10:27:24 -0600452
Simon Glass2a2d91d2018-07-06 10:27:28 -0600453class TestFdtUtil(unittest.TestCase):
454 """Tests for the fdt_util module
455
456 This module will likely be mostly replaced at some point, once upstream
457 libfdt has better Python support. For now, this provides tests for current
458 functionality.
459 """
460 @classmethod
461 def setUpClass(cls):
462 tools.PrepareOutputDir(None)
463
Simon Glasse0e62752018-10-01 21:12:41 -0600464 @classmethod
465 def tearDownClass(cls):
466 tools.FinaliseOutputDir()
467
Simon Glass2a2d91d2018-07-06 10:27:28 -0600468 def setUp(self):
469 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
470 self.node = self.dtb.GetNode('/spl-test')
471
472 def testGetInt(self):
473 self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
474 self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
475
476 with self.assertRaises(ValueError) as e:
477 self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
478 self.assertIn("property 'intarray' has list value: expecting a single "
479 'integer', str(e.exception))
480
481 def testGetString(self):
482 self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
483 self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
484 'test'))
485
486 with self.assertRaises(ValueError) as e:
487 self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
488 self.assertIn("property 'stringarray' has list value: expecting a "
489 'single string', str(e.exception))
490
491 def testGetBool(self):
492 self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
493 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
494 self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
495 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
496
Simon Glass3af8e492018-07-17 13:25:40 -0600497 def testGetByte(self):
498 self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
499 self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
500
501 with self.assertRaises(ValueError) as e:
502 fdt_util.GetByte(self.node, 'longbytearray')
503 self.assertIn("property 'longbytearray' has list value: expecting a "
504 'single byte', str(e.exception))
505
506 with self.assertRaises(ValueError) as e:
507 fdt_util.GetByte(self.node, 'intval')
508 self.assertIn("property 'intval' has length 4, expecting 1",
509 str(e.exception))
510
Simon Glass94a7c602018-07-17 13:25:46 -0600511 def testGetPhandleList(self):
512 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
513 node = dtb.GetNode('/phandle-source2')
514 self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
515 node = dtb.GetNode('/phandle-source')
516 self.assertEqual([1, 2, 11, 3, 12, 13, 1],
517 fdt_util.GetPhandleList(node, 'clocks'))
518 self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
519
Simon Glass53af22a2018-07-17 13:25:32 -0600520 def testGetDataType(self):
521 self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
522 self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
523 str))
524 with self.assertRaises(ValueError) as e:
525 self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
526 bool))
Simon Glass2a2d91d2018-07-06 10:27:28 -0600527 def testFdtCellsToCpu(self):
528 val = self.node.props['intarray'].value
529 self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
530 self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
531
532 dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
Simon Glasse66d3182019-05-17 22:00:40 -0600533 node1 = dtb2.GetNode('/test1')
534 val = node1.props['reg'].value
Simon Glass2a2d91d2018-07-06 10:27:28 -0600535 self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
536
Simon Glasse66d3182019-05-17 22:00:40 -0600537 node2 = dtb2.GetNode('/test2')
538 val = node2.props['reg'].value
539 self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
540 self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
541 2))
542 self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
543
Simon Glass2a2d91d2018-07-06 10:27:28 -0600544 def testEnsureCompiled(self):
Simon Glassa004f292019-07-20 12:23:49 -0600545 """Test a degenerate case of this function (file already compiled)"""
Simon Glass2a2d91d2018-07-06 10:27:28 -0600546 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
547 self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
548
Simon Glassa004f292019-07-20 12:23:49 -0600549 def testEnsureCompiledTmpdir(self):
550 """Test providing a temporary directory"""
551 try:
552 old_outdir = tools.outdir
553 tools.outdir= None
554 tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
555 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts',
556 tmpdir)
557 self.assertEqual(tmpdir, os.path.dirname(dtb))
558 shutil.rmtree(tmpdir)
559 finally:
560 tools.outdir= old_outdir
561
Simon Glass2a2d91d2018-07-06 10:27:28 -0600562
563def RunTestCoverage():
564 """Run the tests and check that we get 100% coverage"""
565 test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
566 ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
567
568
Simon Glass2ba98752018-07-06 10:27:24 -0600569def RunTests(args):
570 """Run all the test we have for the fdt model
571
572 Args:
573 args: List of positional args provided to fdt. This can hold a test
574 name to execute (as in 'fdt -t testFdt', for example)
575 """
576 result = unittest.TestResult()
577 sys.argv = [sys.argv[0]]
578 test_name = args and args[0] or None
Simon Glass2a2d91d2018-07-06 10:27:28 -0600579 for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
Simon Glass2ba98752018-07-06 10:27:24 -0600580 if test_name:
581 try:
582 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
583 except AttributeError:
584 continue
585 else:
586 suite = unittest.TestLoader().loadTestsFromTestCase(module)
587 suite.run(result)
588
Simon Glass90a81322019-05-17 22:00:31 -0600589 print(result)
Simon Glass2ba98752018-07-06 10:27:24 -0600590 for _, err in result.errors:
Simon Glass90a81322019-05-17 22:00:31 -0600591 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600592 for _, err in result.failures:
Simon Glass90a81322019-05-17 22:00:31 -0600593 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600594
595if __name__ != '__main__':
596 sys.exit(1)
597
598parser = OptionParser()
Simon Glass2a2d91d2018-07-06 10:27:28 -0600599parser.add_option('-B', '--build-dir', type='string', default='b',
600 help='Directory containing the build output')
Simon Glass11ae93e2018-10-01 21:12:47 -0600601parser.add_option('-P', '--processes', type=int,
602 help='set number of processes to use for running tests')
Simon Glass2ba98752018-07-06 10:27:24 -0600603parser.add_option('-t', '--test', action='store_true', dest='test',
604 default=False, help='run tests')
Simon Glass2a2d91d2018-07-06 10:27:28 -0600605parser.add_option('-T', '--test-coverage', action='store_true',
606 default=False, help='run tests and check for 100% coverage')
Simon Glass2ba98752018-07-06 10:27:24 -0600607(options, args) = parser.parse_args()
608
609# Run our meagre tests
610if options.test:
611 RunTests(args)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600612elif options.test_coverage:
613 RunTestCoverage()