blob: dc6943f73373a85c355f884ae23358617446eac9 [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
7from optparse import OptionParser
8import glob
9import os
Simon Glassb8d2daa2019-07-20 12:23:49 -060010import shutil
Simon Glass0ed50752018-07-06 10:27:24 -060011import sys
Simon Glassb8d2daa2019-07-20 12:23:49 -060012import tempfile
Simon Glass0ed50752018-07-06 10:27:24 -060013import unittest
14
15# Bring in the patman libraries
16our_path = os.path.dirname(os.path.realpath(__file__))
Simon Glass42143162020-04-17 18:09:05 -060017sys.path.insert(1, os.path.join(our_path, '..'))
Simon Glass0ed50752018-07-06 10:27:24 -060018
Simon Glassa997ea52020-04-17 18:09:04 -060019from dtoc import fdt
20from dtoc import fdt_util
21from dtoc.fdt_util import fdt32_to_cpu
Simon Glassc9a032c2020-11-08 20:36:17 -070022from fdt import Type, BytesToValue
Simon Glass0ed50752018-07-06 10:27:24 -060023import libfdt
Simon Glassa997ea52020-04-17 18:09:04 -060024from patman import command
25from patman import test_util
26from patman import tools
Simon Glass0ed50752018-07-06 10:27:24 -060027
Simon Glass4df8a0c2018-07-06 10:27:29 -060028def _GetPropertyValue(dtb, node, prop_name):
29 """Low-level function to get the property value based on its offset
30
31 This looks directly in the device tree at the property's offset to find
32 its value. It is useful as a check that the property is in the correct
33 place.
34
35 Args:
36 node: Node to look in
37 prop_name: Property name to find
38
39 Returns:
40 Tuple:
41 Prop object found
42 Value of property as a string (found using property offset)
43 """
44 prop = node.props[prop_name]
45
46 # Add 12, which is sizeof(struct fdt_property), to get to start of data
47 offset = prop.GetOffset() + 12
48 data = dtb.GetContents()[offset:offset + len(prop.value)]
Simon Glass632b84c2020-11-08 20:36:20 -070049 return prop, [chr(x) for x in data]
Simon Glass4df8a0c2018-07-06 10:27:29 -060050
51
Simon Glass0ed50752018-07-06 10:27:24 -060052class TestFdt(unittest.TestCase):
53 """Tests for the Fdt module
54
55 This includes unit tests for some functions and functional tests for the fdt
56 module.
57 """
58 @classmethod
59 def setUpClass(cls):
60 tools.PrepareOutputDir(None)
61
62 @classmethod
63 def tearDownClass(cls):
Simon Glass752e7552018-10-01 21:12:41 -060064 tools.FinaliseOutputDir()
Simon Glass0ed50752018-07-06 10:27:24 -060065
66 def setUp(self):
67 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
68
69 def testFdt(self):
70 """Test that we can open an Fdt"""
71 self.dtb.Scan()
72 root = self.dtb.GetRoot()
73 self.assertTrue(isinstance(root, fdt.Node))
74
75 def testGetNode(self):
76 """Test the GetNode() method"""
77 node = self.dtb.GetNode('/spl-test')
78 self.assertTrue(isinstance(node, fdt.Node))
Simon Glass3b9a8292019-07-20 12:23:39 -060079
Simon Glass0ed50752018-07-06 10:27:24 -060080 node = self.dtb.GetNode('/i2c@0/pmic@9')
81 self.assertTrue(isinstance(node, fdt.Node))
82 self.assertEqual('pmic@9', node.name)
Simon Glass9c526332018-07-06 10:27:28 -060083 self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
Simon Glass0ed50752018-07-06 10:27:24 -060084
Simon Glass3b9a8292019-07-20 12:23:39 -060085 node = self.dtb.GetNode('/')
86 self.assertTrue(isinstance(node, fdt.Node))
87 self.assertEqual(0, node.Offset())
88
Simon Glass0ed50752018-07-06 10:27:24 -060089 def testFlush(self):
90 """Check that we can flush the device tree out to its file"""
91 fname = self.dtb._fname
Simon Glass80d54ee2019-05-17 22:00:39 -060092 with open(fname, 'rb') as fd:
Simon Glass0ed50752018-07-06 10:27:24 -060093 data = fd.read()
94 os.remove(fname)
95 with self.assertRaises(IOError):
Simon Glass80d54ee2019-05-17 22:00:39 -060096 open(fname, 'rb')
Simon Glass0ed50752018-07-06 10:27:24 -060097 self.dtb.Flush()
Simon Glass80d54ee2019-05-17 22:00:39 -060098 with open(fname, 'rb') as fd:
Simon Glass0ed50752018-07-06 10:27:24 -060099 data = fd.read()
100
101 def testPack(self):
102 """Test that packing a device tree works"""
103 self.dtb.Pack()
104
105 def testGetFdt(self):
106 """Tetst that we can access the raw device-tree data"""
Simon Glass792d2392018-07-06 10:27:27 -0600107 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
Simon Glass0ed50752018-07-06 10:27:24 -0600108
109 def testGetProps(self):
110 """Tests obtaining a list of properties"""
111 node = self.dtb.GetNode('/spl-test')
112 props = self.dtb.GetProps(node)
113 self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
Simon Glass9c526332018-07-06 10:27:28 -0600114 'intarray', 'intval', 'longbytearray', 'notstring',
Simon Glass0ed50752018-07-06 10:27:24 -0600115 'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
116 sorted(props.keys()))
117
118 def testCheckError(self):
119 """Tests the ChecKError() function"""
120 with self.assertRaises(ValueError) as e:
Simon Glass9c526332018-07-06 10:27:28 -0600121 fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
Simon Glass0ed50752018-07-06 10:27:24 -0600122 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
123
Simon Glasse2d65282018-07-17 13:25:46 -0600124 def testGetFdt(self):
125 node = self.dtb.GetNode('/spl-test')
126 self.assertEqual(self.dtb, node.GetFdt())
Simon Glass0ed50752018-07-06 10:27:24 -0600127
Simon Glass5872f0c2019-05-17 22:00:41 -0600128 def testBytesToValue(self):
129 self.assertEqual(BytesToValue(b'this\0is\0'),
Simon Glassc9a032c2020-11-08 20:36:17 -0700130 (Type.STRING, ['this', 'is']))
Simon Glass5872f0c2019-05-17 22:00:41 -0600131
Simon Glass0ed50752018-07-06 10:27:24 -0600132class TestNode(unittest.TestCase):
133 """Test operation of the Node class"""
134
135 @classmethod
136 def setUpClass(cls):
137 tools.PrepareOutputDir(None)
138
139 @classmethod
140 def tearDownClass(cls):
Simon Glass752e7552018-10-01 21:12:41 -0600141 tools.FinaliseOutputDir()
Simon Glass0ed50752018-07-06 10:27:24 -0600142
143 def setUp(self):
144 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
145 self.node = self.dtb.GetNode('/spl-test')
146
147 def testOffset(self):
148 """Tests that we can obtain the offset of a node"""
149 self.assertTrue(self.node.Offset() > 0)
150
151 def testDelete(self):
152 """Tests that we can delete a property"""
153 node2 = self.dtb.GetNode('/spl-test2')
154 offset1 = node2.Offset()
155 self.node.DeleteProp('intval')
156 offset2 = node2.Offset()
157 self.assertTrue(offset2 < offset1)
158 self.node.DeleteProp('intarray')
159 offset3 = node2.Offset()
160 self.assertTrue(offset3 < offset2)
Simon Glass9c526332018-07-06 10:27:28 -0600161 with self.assertRaises(libfdt.FdtException):
162 self.node.DeleteProp('missing')
Simon Glass0ed50752018-07-06 10:27:24 -0600163
Simon Glass4df8a0c2018-07-06 10:27:29 -0600164 def testDeleteGetOffset(self):
165 """Test that property offset update when properties are deleted"""
166 self.node.DeleteProp('intval')
167 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
168 self.assertEqual(prop.value, value)
169
Simon Glass0ed50752018-07-06 10:27:24 -0600170 def testFindNode(self):
Simon Glassaa1a5d72018-07-17 13:25:41 -0600171 """Tests that we can find a node using the FindNode() functoin"""
172 node = self.dtb.GetRoot().FindNode('i2c@0')
Simon Glass0ed50752018-07-06 10:27:24 -0600173 self.assertEqual('i2c@0', node.name)
Simon Glassaa1a5d72018-07-17 13:25:41 -0600174 subnode = node.FindNode('pmic@9')
Simon Glass0ed50752018-07-06 10:27:24 -0600175 self.assertEqual('pmic@9', subnode.name)
Simon Glassaa1a5d72018-07-17 13:25:41 -0600176 self.assertEqual(None, node.FindNode('missing'))
Simon Glass0ed50752018-07-06 10:27:24 -0600177
Simon Glass4df8a0c2018-07-06 10:27:29 -0600178 def testRefreshMissingNode(self):
179 """Test refreshing offsets when an extra node is present in dtb"""
180 # Delete it from our tables, not the device tree
181 del self.dtb._root.subnodes[-1]
182 with self.assertRaises(ValueError) as e:
183 self.dtb.Refresh()
184 self.assertIn('Internal error, offset', str(e.exception))
185
186 def testRefreshExtraNode(self):
187 """Test refreshing offsets when an expected node is missing"""
188 # Delete it from the device tre, not our tables
189 self.dtb.GetFdtObj().del_node(self.node.Offset())
190 with self.assertRaises(ValueError) as e:
191 self.dtb.Refresh()
192 self.assertIn('Internal error, node name mismatch '
193 'spl-test != spl-test2', str(e.exception))
194
195 def testRefreshMissingProp(self):
196 """Test refreshing offsets when an extra property is present in dtb"""
197 # Delete it from our tables, not the device tree
198 del self.node.props['notstring']
199 with self.assertRaises(ValueError) as e:
200 self.dtb.Refresh()
201 self.assertIn("Internal error, property 'notstring' missing, offset ",
202 str(e.exception))
203
Simon Glasse2d65282018-07-17 13:25:46 -0600204 def testLookupPhandle(self):
205 """Test looking up a single phandle"""
206 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
207 node = dtb.GetNode('/phandle-source2')
208 prop = node.props['clocks']
209 target = dtb.GetNode('/phandle-target')
210 self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
211
Simon Glass0ed50752018-07-06 10:27:24 -0600212
213class TestProp(unittest.TestCase):
214 """Test operation of the Prop class"""
215
216 @classmethod
217 def setUpClass(cls):
218 tools.PrepareOutputDir(None)
219
220 @classmethod
221 def tearDownClass(cls):
Simon Glass752e7552018-10-01 21:12:41 -0600222 tools.FinaliseOutputDir()
Simon Glass0ed50752018-07-06 10:27:24 -0600223
224 def setUp(self):
225 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
226 self.node = self.dtb.GetNode('/spl-test')
227 self.fdt = self.dtb.GetFdtObj()
228
Simon Glassc5eddc82018-07-06 10:27:30 -0600229 def testMissingNode(self):
230 self.assertEqual(None, self.dtb.GetNode('missing'))
231
Simon Glass9c526332018-07-06 10:27:28 -0600232 def testPhandle(self):
233 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
Simon Glass609e2b12018-07-06 10:27:31 -0600234 node = dtb.GetNode('/phandle-source2')
235 prop = node.props['clocks']
236 self.assertTrue(fdt32_to_cpu(prop.value) > 0)
Simon Glass9c526332018-07-06 10:27:28 -0600237
238 def _ConvertProp(self, prop_name):
239 """Helper function to look up a property in self.node and return it
240
241 Args:
242 Property name to find
243
244 Return fdt.Prop object for this property
245 """
Simon Glassb474c762018-07-26 14:02:13 -0600246 p = self.fdt.getprop(self.node.Offset(), prop_name)
Simon Glass9c526332018-07-06 10:27:28 -0600247 return fdt.Prop(self.node, -1, prop_name, p)
248
249 def testMakeProp(self):
250 """Test we can convert all the the types that are supported"""
251 prop = self._ConvertProp('boolval')
Simon Glassc9a032c2020-11-08 20:36:17 -0700252 self.assertEqual(Type.BOOL, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600253 self.assertEqual(True, prop.value)
254
255 prop = self._ConvertProp('intval')
Simon Glassc9a032c2020-11-08 20:36:17 -0700256 self.assertEqual(Type.INT, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600257 self.assertEqual(1, fdt32_to_cpu(prop.value))
258
259 prop = self._ConvertProp('intarray')
Simon Glassc9a032c2020-11-08 20:36:17 -0700260 self.assertEqual(Type.INT, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600261 val = [fdt32_to_cpu(val) for val in prop.value]
262 self.assertEqual([2, 3, 4], val)
263
264 prop = self._ConvertProp('byteval')
Simon Glassc9a032c2020-11-08 20:36:17 -0700265 self.assertEqual(Type.BYTE, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600266 self.assertEqual(5, ord(prop.value))
267
268 prop = self._ConvertProp('longbytearray')
Simon Glassc9a032c2020-11-08 20:36:17 -0700269 self.assertEqual(Type.BYTE, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600270 val = [ord(val) for val in prop.value]
271 self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
272
273 prop = self._ConvertProp('stringval')
Simon Glassc9a032c2020-11-08 20:36:17 -0700274 self.assertEqual(Type.STRING, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600275 self.assertEqual('message', prop.value)
276
277 prop = self._ConvertProp('stringarray')
Simon Glassc9a032c2020-11-08 20:36:17 -0700278 self.assertEqual(Type.STRING, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600279 self.assertEqual(['multi-word', 'message'], prop.value)
280
281 prop = self._ConvertProp('notstring')
Simon Glassc9a032c2020-11-08 20:36:17 -0700282 self.assertEqual(Type.BYTE, prop.type)
Simon Glass9c526332018-07-06 10:27:28 -0600283 val = [ord(val) for val in prop.value]
284 self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
285
Simon Glass0ed50752018-07-06 10:27:24 -0600286 def testGetEmpty(self):
287 """Tests the GetEmpty() function for the various supported types"""
Simon Glassc9a032c2020-11-08 20:36:17 -0700288 self.assertEqual(True, fdt.Prop.GetEmpty(Type.BOOL))
289 self.assertEqual(chr(0), fdt.Prop.GetEmpty(Type.BYTE))
290 self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(Type.INT))
291 self.assertEqual('', fdt.Prop.GetEmpty(Type.STRING))
Simon Glass0ed50752018-07-06 10:27:24 -0600292
293 def testGetOffset(self):
294 """Test we can get the offset of a property"""
Simon Glass4df8a0c2018-07-06 10:27:29 -0600295 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
296 self.assertEqual(prop.value, value)
Simon Glass0ed50752018-07-06 10:27:24 -0600297
298 def testWiden(self):
299 """Test widening of values"""
300 node2 = self.dtb.GetNode('/spl-test2')
Simon Glass8034e4d2020-10-03 11:31:27 -0600301 node3 = self.dtb.GetNode('/spl-test3')
Simon Glass0ed50752018-07-06 10:27:24 -0600302 prop = self.node.props['intval']
303
304 # No action
305 prop2 = node2.props['intval']
306 prop.Widen(prop2)
Simon Glassc9a032c2020-11-08 20:36:17 -0700307 self.assertEqual(Type.INT, prop.type)
Simon Glass0ed50752018-07-06 10:27:24 -0600308 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)
Simon Glassc9a032c2020-11-08 20:36:17 -0700313 self.assertEqual(Type.INT, prop.type)
Simon Glass0ed50752018-07-06 10:27:24 -0600314 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']
Simon Glass8034e4d2020-10-03 11:31:27 -0600320 prop3 = node3.props['longbytearray']
Simon Glass0ed50752018-07-06 10:27:24 -0600321 self.assertFalse(isinstance(prop2.value, list))
322 self.assertEqual(4, len(prop2.value))
Simon Glass8034e4d2020-10-03 11:31:27 -0600323 self.assertEqual(b'\x09\x0a\x0b\x0c', prop2.value)
Simon Glass0ed50752018-07-06 10:27:24 -0600324 prop2.Widen(prop)
325 self.assertTrue(isinstance(prop2.value, list))
326 self.assertEqual(9, len(prop2.value))
Simon Glass8034e4d2020-10-03 11:31:27 -0600327 self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\0',
328 '\0', '\0', '\0', '\0'], prop2.value)
329 prop3.Widen(prop)
330 self.assertTrue(isinstance(prop3.value, list))
331 self.assertEqual(9, len(prop3.value))
332 self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\x0d',
333 '\x0e', '\x0f', '\x10', '\0'], prop3.value)
Simon Glass0ed50752018-07-06 10:27:24 -0600334
335 # Similarly for a string array
336 prop = self.node.props['stringval']
337 prop2 = node2.props['stringarray']
338 self.assertFalse(isinstance(prop.value, list))
339 self.assertEqual(7, len(prop.value))
340 prop.Widen(prop2)
341 self.assertTrue(isinstance(prop.value, list))
342 self.assertEqual(3, len(prop.value))
343
344 # Enlarging an existing array
345 prop = self.node.props['stringarray']
346 prop2 = node2.props['stringarray']
347 self.assertTrue(isinstance(prop.value, list))
348 self.assertEqual(2, len(prop.value))
349 prop.Widen(prop2)
350 self.assertTrue(isinstance(prop.value, list))
351 self.assertEqual(3, len(prop.value))
352
Simon Glasse80c5562018-07-06 10:27:38 -0600353 def testAdd(self):
354 """Test adding properties"""
355 self.fdt.pack()
356 # This function should automatically expand the device tree
357 self.node.AddZeroProp('one')
358 self.node.AddZeroProp('two')
359 self.node.AddZeroProp('three')
Simon Glasseddd7292018-09-14 04:57:13 -0600360 self.dtb.Sync(auto_resize=True)
Simon Glasse80c5562018-07-06 10:27:38 -0600361
362 # Updating existing properties should be OK, since the device-tree size
363 # does not change
364 self.fdt.pack()
365 self.node.SetInt('one', 1)
366 self.node.SetInt('two', 2)
367 self.node.SetInt('three', 3)
Simon Glasseddd7292018-09-14 04:57:13 -0600368 self.dtb.Sync(auto_resize=False)
Simon Glasse80c5562018-07-06 10:27:38 -0600369
370 # This should fail since it would need to increase the device-tree size
Simon Glasseddd7292018-09-14 04:57:13 -0600371 self.node.AddZeroProp('four')
Simon Glasse80c5562018-07-06 10:27:38 -0600372 with self.assertRaises(libfdt.FdtException) as e:
Simon Glasseddd7292018-09-14 04:57:13 -0600373 self.dtb.Sync(auto_resize=False)
Simon Glasse80c5562018-07-06 10:27:38 -0600374 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
Simon Glassccd25262018-09-14 04:57:16 -0600375 self.dtb.Sync(auto_resize=True)
Simon Glasse80c5562018-07-06 10:27:38 -0600376
Simon Glasseddd7292018-09-14 04:57:13 -0600377 def testAddNode(self):
378 self.fdt.pack()
Simon Glassf3a17962018-09-14 04:57:15 -0600379 self.node.AddSubnode('subnode')
380 with self.assertRaises(libfdt.FdtException) as e:
381 self.dtb.Sync(auto_resize=False)
382 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
383
384 self.dtb.Sync(auto_resize=True)
385 offset = self.fdt.path_offset('/spl-test/subnode')
386 self.assertTrue(offset > 0)
Simon Glasseddd7292018-09-14 04:57:13 -0600387
Simon Glassccd25262018-09-14 04:57:16 -0600388 def testAddMore(self):
389 """Test various other methods for adding and setting properties"""
390 self.node.AddZeroProp('one')
391 self.dtb.Sync(auto_resize=True)
392 data = self.fdt.getprop(self.node.Offset(), 'one')
393 self.assertEqual(0, fdt32_to_cpu(data))
394
395 self.node.SetInt('one', 1)
396 self.dtb.Sync(auto_resize=False)
397 data = self.fdt.getprop(self.node.Offset(), 'one')
398 self.assertEqual(1, fdt32_to_cpu(data))
399
400 val = '123' + chr(0) + '456'
401 self.node.AddString('string', val)
402 self.dtb.Sync(auto_resize=True)
403 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glass1cd40082019-05-17 22:00:36 -0600404 self.assertEqual(tools.ToBytes(val) + b'\0', data)
Simon Glassccd25262018-09-14 04:57:16 -0600405
406 self.fdt.pack()
407 self.node.SetString('string', val + 'x')
408 with self.assertRaises(libfdt.FdtException) as e:
409 self.dtb.Sync(auto_resize=False)
410 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
411 self.node.SetString('string', val[:-1])
412
413 prop = self.node.props['string']
Simon Glass1cd40082019-05-17 22:00:36 -0600414 prop.SetData(tools.ToBytes(val))
Simon Glassccd25262018-09-14 04:57:16 -0600415 self.dtb.Sync(auto_resize=False)
416 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glass1cd40082019-05-17 22:00:36 -0600417 self.assertEqual(tools.ToBytes(val), data)
Simon Glassccd25262018-09-14 04:57:16 -0600418
419 self.node.AddEmptyProp('empty', 5)
420 self.dtb.Sync(auto_resize=True)
421 prop = self.node.props['empty']
Simon Glass1cd40082019-05-17 22:00:36 -0600422 prop.SetData(tools.ToBytes(val))
Simon Glassccd25262018-09-14 04:57:16 -0600423 self.dtb.Sync(auto_resize=False)
424 data = self.fdt.getprop(self.node.Offset(), 'empty')
Simon Glass1cd40082019-05-17 22:00:36 -0600425 self.assertEqual(tools.ToBytes(val), data)
Simon Glassccd25262018-09-14 04:57:16 -0600426
Simon Glass1cd40082019-05-17 22:00:36 -0600427 self.node.SetData('empty', b'123')
428 self.assertEqual(b'123', prop.bytes)
Simon Glassccd25262018-09-14 04:57:16 -0600429
Simon Glassf67c99c2020-07-09 18:39:44 -0600430 # Trying adding a lot of data at once
431 self.node.AddData('data', tools.GetBytes(65, 20000))
432 self.dtb.Sync(auto_resize=True)
433
Simon Glassb8a49292018-09-14 04:57:17 -0600434 def testFromData(self):
435 dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
436 self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
437
438 self.node.AddEmptyProp('empty', 5)
439 self.dtb.Sync(auto_resize=True)
440 self.assertTrue(dtb2.GetContents() != self.dtb.GetContents())
441
Simon Glassa683a5f2019-07-20 12:23:37 -0600442 def testMissingSetInt(self):
443 """Test handling of a missing property with SetInt"""
444 with self.assertRaises(ValueError) as e:
445 self.node.SetInt('one', 1)
446 self.assertIn("node '/spl-test': Missing property 'one'",
447 str(e.exception))
448
449 def testMissingSetData(self):
450 """Test handling of a missing property with SetData"""
451 with self.assertRaises(ValueError) as e:
452 self.node.SetData('one', b'data')
453 self.assertIn("node '/spl-test': Missing property 'one'",
454 str(e.exception))
455
456 def testMissingSetString(self):
457 """Test handling of a missing property with SetString"""
458 with self.assertRaises(ValueError) as e:
459 self.node.SetString('one', 1)
460 self.assertIn("node '/spl-test': Missing property 'one'",
461 str(e.exception))
462
Simon Glass74f5feb2019-07-20 12:24:08 -0600463 def testGetFilename(self):
464 """Test the dtb filename can be provided"""
465 self.assertEqual(tools.GetOutputFilename('source.dtb'),
466 self.dtb.GetFilename())
467
Simon Glass0ed50752018-07-06 10:27:24 -0600468
Simon Glass9c526332018-07-06 10:27:28 -0600469class TestFdtUtil(unittest.TestCase):
470 """Tests for the fdt_util module
471
472 This module will likely be mostly replaced at some point, once upstream
473 libfdt has better Python support. For now, this provides tests for current
474 functionality.
475 """
476 @classmethod
477 def setUpClass(cls):
478 tools.PrepareOutputDir(None)
479
Simon Glass752e7552018-10-01 21:12:41 -0600480 @classmethod
481 def tearDownClass(cls):
482 tools.FinaliseOutputDir()
483
Simon Glass9c526332018-07-06 10:27:28 -0600484 def setUp(self):
485 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
486 self.node = self.dtb.GetNode('/spl-test')
487
488 def testGetInt(self):
489 self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
490 self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
491
492 with self.assertRaises(ValueError) as e:
493 self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
494 self.assertIn("property 'intarray' has list value: expecting a single "
495 'integer', str(e.exception))
496
497 def testGetString(self):
498 self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
499 self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
500 'test'))
501
502 with self.assertRaises(ValueError) as e:
503 self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
504 self.assertIn("property 'stringarray' has list value: expecting a "
505 'single string', str(e.exception))
506
507 def testGetBool(self):
508 self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
509 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
510 self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
511 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
512
Simon Glass53f53992018-07-17 13:25:40 -0600513 def testGetByte(self):
514 self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
515 self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
516
517 with self.assertRaises(ValueError) as e:
518 fdt_util.GetByte(self.node, 'longbytearray')
519 self.assertIn("property 'longbytearray' has list value: expecting a "
520 'single byte', str(e.exception))
521
522 with self.assertRaises(ValueError) as e:
523 fdt_util.GetByte(self.node, 'intval')
524 self.assertIn("property 'intval' has length 4, expecting 1",
525 str(e.exception))
526
Simon Glasse2d65282018-07-17 13:25:46 -0600527 def testGetPhandleList(self):
528 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
529 node = dtb.GetNode('/phandle-source2')
530 self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
531 node = dtb.GetNode('/phandle-source')
532 self.assertEqual([1, 2, 11, 3, 12, 13, 1],
533 fdt_util.GetPhandleList(node, 'clocks'))
534 self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
535
Simon Glass91710b32018-07-17 13:25:32 -0600536 def testGetDataType(self):
537 self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
538 self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
539 str))
540 with self.assertRaises(ValueError) as e:
541 self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
542 bool))
Simon Glass9c526332018-07-06 10:27:28 -0600543 def testFdtCellsToCpu(self):
544 val = self.node.props['intarray'].value
545 self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
546 self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
547
548 dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
Simon Glassb0a34a42019-05-17 22:00:40 -0600549 node1 = dtb2.GetNode('/test1')
550 val = node1.props['reg'].value
Simon Glass9c526332018-07-06 10:27:28 -0600551 self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
552
Simon Glassb0a34a42019-05-17 22:00:40 -0600553 node2 = dtb2.GetNode('/test2')
554 val = node2.props['reg'].value
555 self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
556 self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
557 2))
558 self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
559
Simon Glass9c526332018-07-06 10:27:28 -0600560 def testEnsureCompiled(self):
Simon Glassb8d2daa2019-07-20 12:23:49 -0600561 """Test a degenerate case of this function (file already compiled)"""
Simon Glass9c526332018-07-06 10:27:28 -0600562 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
563 self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
564
Simon Glassb8d2daa2019-07-20 12:23:49 -0600565 def testEnsureCompiledTmpdir(self):
566 """Test providing a temporary directory"""
567 try:
568 old_outdir = tools.outdir
569 tools.outdir= None
570 tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
571 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts',
572 tmpdir)
573 self.assertEqual(tmpdir, os.path.dirname(dtb))
574 shutil.rmtree(tmpdir)
575 finally:
576 tools.outdir= old_outdir
577
Simon Glass9c526332018-07-06 10:27:28 -0600578
579def RunTestCoverage():
580 """Run the tests and check that we get 100% coverage"""
581 test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
582 ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
583
584
Simon Glass0ed50752018-07-06 10:27:24 -0600585def RunTests(args):
586 """Run all the test we have for the fdt model
587
588 Args:
589 args: List of positional args provided to fdt. This can hold a test
590 name to execute (as in 'fdt -t testFdt', for example)
591 """
592 result = unittest.TestResult()
593 sys.argv = [sys.argv[0]]
594 test_name = args and args[0] or None
Simon Glass9c526332018-07-06 10:27:28 -0600595 for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
Simon Glass0ed50752018-07-06 10:27:24 -0600596 if test_name:
597 try:
598 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
599 except AttributeError:
600 continue
601 else:
602 suite = unittest.TestLoader().loadTestsFromTestCase(module)
603 suite.run(result)
604
Simon Glass61b88e52019-05-17 22:00:31 -0600605 print(result)
Simon Glass0ed50752018-07-06 10:27:24 -0600606 for _, err in result.errors:
Simon Glass61b88e52019-05-17 22:00:31 -0600607 print(err)
Simon Glass0ed50752018-07-06 10:27:24 -0600608 for _, err in result.failures:
Simon Glass61b88e52019-05-17 22:00:31 -0600609 print(err)
Simon Glass0ed50752018-07-06 10:27:24 -0600610
611if __name__ != '__main__':
612 sys.exit(1)
613
614parser = OptionParser()
Simon Glass9c526332018-07-06 10:27:28 -0600615parser.add_option('-B', '--build-dir', type='string', default='b',
616 help='Directory containing the build output')
Simon Glass7057d022018-10-01 21:12:47 -0600617parser.add_option('-P', '--processes', type=int,
618 help='set number of processes to use for running tests')
Simon Glass0ed50752018-07-06 10:27:24 -0600619parser.add_option('-t', '--test', action='store_true', dest='test',
620 default=False, help='run tests')
Simon Glass9c526332018-07-06 10:27:28 -0600621parser.add_option('-T', '--test-coverage', action='store_true',
622 default=False, help='run tests and check for 100% coverage')
Simon Glass0ed50752018-07-06 10:27:24 -0600623(options, args) = parser.parse_args()
624
625# Run our meagre tests
626if options.test:
627 RunTests(args)
Simon Glass9c526332018-07-06 10:27:28 -0600628elif options.test_coverage:
629 RunTestCoverage()