blob: 3316757e61e3ede85355587edc4dd9c290c10838 [file] [log] [blame]
Simon Glassfc017822019-10-31 07:42:54 -06001#!/usr/bin/env python3
Simon Glass0ed50752018-07-06 10:27:24 -06002# 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
Simon Glassb8d2daa2019-07-20 12:23:49 -060012import shutil
Simon Glass0ed50752018-07-06 10:27:24 -060013import sys
Simon Glassb8d2daa2019-07-20 12:23:49 -060014import tempfile
Simon Glass0ed50752018-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 Glass5872f0c2019-05-17 22:00:41 -060024from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
Simon Glass9c526332018-07-06 10:27:28 -060025import fdt_util
Simon Glass0ed50752018-07-06 10:27:24 -060026from fdt_util import fdt32_to_cpu
27import libfdt
28import test_util
29import tools
30
Simon Glass4df8a0c2018-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 Glass1cd40082019-05-17 22:00:36 -060052 return prop, [tools.ToChar(x) for x in data]
Simon Glass4df8a0c2018-07-06 10:27:29 -060053
54
Simon Glass0ed50752018-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 Glass752e7552018-10-01 21:12:41 -060067 tools.FinaliseOutputDir()
Simon Glass0ed50752018-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 Glass3b9a8292019-07-20 12:23:39 -060082
Simon Glass0ed50752018-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 Glass9c526332018-07-06 10:27:28 -060086 self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
Simon Glass0ed50752018-07-06 10:27:24 -060087
Simon Glass3b9a8292019-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 Glass0ed50752018-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 Glass80d54ee2019-05-17 22:00:39 -060095 with open(fname, 'rb') as fd:
Simon Glass0ed50752018-07-06 10:27:24 -060096 data = fd.read()
97 os.remove(fname)
98 with self.assertRaises(IOError):
Simon Glass80d54ee2019-05-17 22:00:39 -060099 open(fname, 'rb')
Simon Glass0ed50752018-07-06 10:27:24 -0600100 self.dtb.Flush()
Simon Glass80d54ee2019-05-17 22:00:39 -0600101 with open(fname, 'rb') as fd:
Simon Glass0ed50752018-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 Glass792d2392018-07-06 10:27:27 -0600110 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
Simon Glass0ed50752018-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 Glass9c526332018-07-06 10:27:28 -0600117 'intarray', 'intval', 'longbytearray', 'notstring',
Simon Glass0ed50752018-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 Glass9c526332018-07-06 10:27:28 -0600124 fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
Simon Glass0ed50752018-07-06 10:27:24 -0600125 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
126
Simon Glasse2d65282018-07-17 13:25:46 -0600127 def testGetFdt(self):
128 node = self.dtb.GetNode('/spl-test')
129 self.assertEqual(self.dtb, node.GetFdt())
Simon Glass0ed50752018-07-06 10:27:24 -0600130
Simon Glass5872f0c2019-05-17 22:00:41 -0600131 def testBytesToValue(self):
132 self.assertEqual(BytesToValue(b'this\0is\0'),
133 (TYPE_STRING, ['this', 'is']))
134
Simon Glass0ed50752018-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 Glass752e7552018-10-01 21:12:41 -0600144 tools.FinaliseOutputDir()
Simon Glass0ed50752018-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 Glass9c526332018-07-06 10:27:28 -0600164 with self.assertRaises(libfdt.FdtException):
165 self.node.DeleteProp('missing')
Simon Glass0ed50752018-07-06 10:27:24 -0600166
Simon Glass4df8a0c2018-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 Glass0ed50752018-07-06 10:27:24 -0600173 def testFindNode(self):
Simon Glassaa1a5d72018-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 Glass0ed50752018-07-06 10:27:24 -0600176 self.assertEqual('i2c@0', node.name)
Simon Glassaa1a5d72018-07-17 13:25:41 -0600177 subnode = node.FindNode('pmic@9')
Simon Glass0ed50752018-07-06 10:27:24 -0600178 self.assertEqual('pmic@9', subnode.name)
Simon Glassaa1a5d72018-07-17 13:25:41 -0600179 self.assertEqual(None, node.FindNode('missing'))
Simon Glass0ed50752018-07-06 10:27:24 -0600180
Simon Glass4df8a0c2018-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 Glasse2d65282018-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 Glass0ed50752018-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 Glass752e7552018-10-01 21:12:41 -0600225 tools.FinaliseOutputDir()
Simon Glass0ed50752018-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 Glassc5eddc82018-07-06 10:27:30 -0600232 def testMissingNode(self):
233 self.assertEqual(None, self.dtb.GetNode('missing'))
234
Simon Glass9c526332018-07-06 10:27:28 -0600235 def testPhandle(self):
236 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
Simon Glass609e2b12018-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 Glass9c526332018-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 Glassb474c762018-07-26 14:02:13 -0600249 p = self.fdt.getprop(self.node.Offset(), prop_name)
Simon Glass9c526332018-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 Glass0ed50752018-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 Glass6bbfafb2019-05-17 22:00:33 -0600293 self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
Simon Glass0ed50752018-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 Glass4df8a0c2018-07-06 10:27:29 -0600298 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
299 self.assertEqual(prop.value, value)
Simon Glass0ed50752018-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 Glasse80c5562018-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 Glasseddd7292018-09-14 04:57:13 -0600353 self.dtb.Sync(auto_resize=True)
Simon Glasse80c5562018-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 Glasseddd7292018-09-14 04:57:13 -0600361 self.dtb.Sync(auto_resize=False)
Simon Glasse80c5562018-07-06 10:27:38 -0600362
363 # This should fail since it would need to increase the device-tree size
Simon Glasseddd7292018-09-14 04:57:13 -0600364 self.node.AddZeroProp('four')
Simon Glasse80c5562018-07-06 10:27:38 -0600365 with self.assertRaises(libfdt.FdtException) as e:
Simon Glasseddd7292018-09-14 04:57:13 -0600366 self.dtb.Sync(auto_resize=False)
Simon Glasse80c5562018-07-06 10:27:38 -0600367 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
Simon Glassccd25262018-09-14 04:57:16 -0600368 self.dtb.Sync(auto_resize=True)
Simon Glasse80c5562018-07-06 10:27:38 -0600369
Simon Glasseddd7292018-09-14 04:57:13 -0600370 def testAddNode(self):
371 self.fdt.pack()
Simon Glassf3a17962018-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 Glasseddd7292018-09-14 04:57:13 -0600380
Simon Glassccd25262018-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 Glass1cd40082019-05-17 22:00:36 -0600397 self.assertEqual(tools.ToBytes(val) + b'\0', data)
Simon Glassccd25262018-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 Glass1cd40082019-05-17 22:00:36 -0600407 prop.SetData(tools.ToBytes(val))
Simon Glassccd25262018-09-14 04:57:16 -0600408 self.dtb.Sync(auto_resize=False)
409 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glass1cd40082019-05-17 22:00:36 -0600410 self.assertEqual(tools.ToBytes(val), data)
Simon Glassccd25262018-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 Glass1cd40082019-05-17 22:00:36 -0600415 prop.SetData(tools.ToBytes(val))
Simon Glassccd25262018-09-14 04:57:16 -0600416 self.dtb.Sync(auto_resize=False)
417 data = self.fdt.getprop(self.node.Offset(), 'empty')
Simon Glass1cd40082019-05-17 22:00:36 -0600418 self.assertEqual(tools.ToBytes(val), data)
Simon Glassccd25262018-09-14 04:57:16 -0600419
Simon Glass1cd40082019-05-17 22:00:36 -0600420 self.node.SetData('empty', b'123')
421 self.assertEqual(b'123', prop.bytes)
Simon Glassccd25262018-09-14 04:57:16 -0600422
Simon Glassb8a49292018-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 Glassa683a5f2019-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 Glass74f5feb2019-07-20 12:24:08 -0600452 def testGetFilename(self):
453 """Test the dtb filename can be provided"""
454 self.assertEqual(tools.GetOutputFilename('source.dtb'),
455 self.dtb.GetFilename())
456
Simon Glass0ed50752018-07-06 10:27:24 -0600457
Simon Glass9c526332018-07-06 10:27:28 -0600458class TestFdtUtil(unittest.TestCase):
459 """Tests for the fdt_util module
460
461 This module will likely be mostly replaced at some point, once upstream
462 libfdt has better Python support. For now, this provides tests for current
463 functionality.
464 """
465 @classmethod
466 def setUpClass(cls):
467 tools.PrepareOutputDir(None)
468
Simon Glass752e7552018-10-01 21:12:41 -0600469 @classmethod
470 def tearDownClass(cls):
471 tools.FinaliseOutputDir()
472
Simon Glass9c526332018-07-06 10:27:28 -0600473 def setUp(self):
474 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
475 self.node = self.dtb.GetNode('/spl-test')
476
477 def testGetInt(self):
478 self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
479 self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
480
481 with self.assertRaises(ValueError) as e:
482 self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
483 self.assertIn("property 'intarray' has list value: expecting a single "
484 'integer', str(e.exception))
485
486 def testGetString(self):
487 self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
488 self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
489 'test'))
490
491 with self.assertRaises(ValueError) as e:
492 self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
493 self.assertIn("property 'stringarray' has list value: expecting a "
494 'single string', str(e.exception))
495
496 def testGetBool(self):
497 self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
498 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
499 self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
500 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
501
Simon Glass53f53992018-07-17 13:25:40 -0600502 def testGetByte(self):
503 self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
504 self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
505
506 with self.assertRaises(ValueError) as e:
507 fdt_util.GetByte(self.node, 'longbytearray')
508 self.assertIn("property 'longbytearray' has list value: expecting a "
509 'single byte', str(e.exception))
510
511 with self.assertRaises(ValueError) as e:
512 fdt_util.GetByte(self.node, 'intval')
513 self.assertIn("property 'intval' has length 4, expecting 1",
514 str(e.exception))
515
Simon Glasse2d65282018-07-17 13:25:46 -0600516 def testGetPhandleList(self):
517 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
518 node = dtb.GetNode('/phandle-source2')
519 self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
520 node = dtb.GetNode('/phandle-source')
521 self.assertEqual([1, 2, 11, 3, 12, 13, 1],
522 fdt_util.GetPhandleList(node, 'clocks'))
523 self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
524
Simon Glass91710b32018-07-17 13:25:32 -0600525 def testGetDataType(self):
526 self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
527 self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
528 str))
529 with self.assertRaises(ValueError) as e:
530 self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
531 bool))
Simon Glass9c526332018-07-06 10:27:28 -0600532 def testFdtCellsToCpu(self):
533 val = self.node.props['intarray'].value
534 self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
535 self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
536
537 dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
Simon Glassb0a34a42019-05-17 22:00:40 -0600538 node1 = dtb2.GetNode('/test1')
539 val = node1.props['reg'].value
Simon Glass9c526332018-07-06 10:27:28 -0600540 self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
541
Simon Glassb0a34a42019-05-17 22:00:40 -0600542 node2 = dtb2.GetNode('/test2')
543 val = node2.props['reg'].value
544 self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
545 self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
546 2))
547 self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
548
Simon Glass9c526332018-07-06 10:27:28 -0600549 def testEnsureCompiled(self):
Simon Glassb8d2daa2019-07-20 12:23:49 -0600550 """Test a degenerate case of this function (file already compiled)"""
Simon Glass9c526332018-07-06 10:27:28 -0600551 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
552 self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
553
Simon Glassb8d2daa2019-07-20 12:23:49 -0600554 def testEnsureCompiledTmpdir(self):
555 """Test providing a temporary directory"""
556 try:
557 old_outdir = tools.outdir
558 tools.outdir= None
559 tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
560 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts',
561 tmpdir)
562 self.assertEqual(tmpdir, os.path.dirname(dtb))
563 shutil.rmtree(tmpdir)
564 finally:
565 tools.outdir= old_outdir
566
Simon Glass9c526332018-07-06 10:27:28 -0600567
568def RunTestCoverage():
569 """Run the tests and check that we get 100% coverage"""
570 test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
571 ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
572
573
Simon Glass0ed50752018-07-06 10:27:24 -0600574def RunTests(args):
575 """Run all the test we have for the fdt model
576
577 Args:
578 args: List of positional args provided to fdt. This can hold a test
579 name to execute (as in 'fdt -t testFdt', for example)
580 """
581 result = unittest.TestResult()
582 sys.argv = [sys.argv[0]]
583 test_name = args and args[0] or None
Simon Glass9c526332018-07-06 10:27:28 -0600584 for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
Simon Glass0ed50752018-07-06 10:27:24 -0600585 if test_name:
586 try:
587 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
588 except AttributeError:
589 continue
590 else:
591 suite = unittest.TestLoader().loadTestsFromTestCase(module)
592 suite.run(result)
593
Simon Glass61b88e52019-05-17 22:00:31 -0600594 print(result)
Simon Glass0ed50752018-07-06 10:27:24 -0600595 for _, err in result.errors:
Simon Glass61b88e52019-05-17 22:00:31 -0600596 print(err)
Simon Glass0ed50752018-07-06 10:27:24 -0600597 for _, err in result.failures:
Simon Glass61b88e52019-05-17 22:00:31 -0600598 print(err)
Simon Glass0ed50752018-07-06 10:27:24 -0600599
600if __name__ != '__main__':
601 sys.exit(1)
602
603parser = OptionParser()
Simon Glass9c526332018-07-06 10:27:28 -0600604parser.add_option('-B', '--build-dir', type='string', default='b',
605 help='Directory containing the build output')
Simon Glass7057d022018-10-01 21:12:47 -0600606parser.add_option('-P', '--processes', type=int,
607 help='set number of processes to use for running tests')
Simon Glass0ed50752018-07-06 10:27:24 -0600608parser.add_option('-t', '--test', action='store_true', dest='test',
609 default=False, help='run tests')
Simon Glass9c526332018-07-06 10:27:28 -0600610parser.add_option('-T', '--test-coverage', action='store_true',
611 default=False, help='run tests and check for 100% coverage')
Simon Glass0ed50752018-07-06 10:27:24 -0600612(options, args) = parser.parse_args()
613
614# Run our meagre tests
615if options.test:
616 RunTests(args)
Simon Glass9c526332018-07-06 10:27:28 -0600617elif options.test_coverage:
618 RunTestCoverage()