blob: d68230713e460b3a7d0033f99dcada29bb3b40e8 [file] [log] [blame]
Simon Glassf7ba5f02019-10-31 07:42:54 -06001#!/usr/bin/env python3
Simon Glass2ba98752018-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 Glassa004f292019-07-20 12:23:49 -060010import shutil
Simon Glass2ba98752018-07-06 10:27:24 -060011import sys
Simon Glassa004f292019-07-20 12:23:49 -060012import tempfile
Simon Glass2ba98752018-07-06 10:27:24 -060013import 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
Simon Glassbf776672020-04-17 18:09:04 -060020from dtoc import fdt
21from dtoc import fdt_util
22from dtoc.fdt_util import fdt32_to_cpu
Simon Glassb5f0daf2019-05-17 22:00:41 -060023from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
Simon Glass2ba98752018-07-06 10:27:24 -060024import libfdt
Simon Glassbf776672020-04-17 18:09:04 -060025from patman import command
26from patman import test_util
27from patman import tools
Simon Glass2ba98752018-07-06 10:27:24 -060028
Simon Glassf9b88b32018-07-06 10:27:29 -060029def _GetPropertyValue(dtb, node, prop_name):
30 """Low-level function to get the property value based on its offset
31
32 This looks directly in the device tree at the property's offset to find
33 its value. It is useful as a check that the property is in the correct
34 place.
35
36 Args:
37 node: Node to look in
38 prop_name: Property name to find
39
40 Returns:
41 Tuple:
42 Prop object found
43 Value of property as a string (found using property offset)
44 """
45 prop = node.props[prop_name]
46
47 # Add 12, which is sizeof(struct fdt_property), to get to start of data
48 offset = prop.GetOffset() + 12
49 data = dtb.GetContents()[offset:offset + len(prop.value)]
Simon Glassf6b64812019-05-17 22:00:36 -060050 return prop, [tools.ToChar(x) for x in data]
Simon Glassf9b88b32018-07-06 10:27:29 -060051
52
Simon Glass2ba98752018-07-06 10:27:24 -060053class TestFdt(unittest.TestCase):
54 """Tests for the Fdt module
55
56 This includes unit tests for some functions and functional tests for the fdt
57 module.
58 """
59 @classmethod
60 def setUpClass(cls):
61 tools.PrepareOutputDir(None)
62
63 @classmethod
64 def tearDownClass(cls):
Simon Glasse0e62752018-10-01 21:12:41 -060065 tools.FinaliseOutputDir()
Simon Glass2ba98752018-07-06 10:27:24 -060066
67 def setUp(self):
68 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
69
70 def testFdt(self):
71 """Test that we can open an Fdt"""
72 self.dtb.Scan()
73 root = self.dtb.GetRoot()
74 self.assertTrue(isinstance(root, fdt.Node))
75
76 def testGetNode(self):
77 """Test the GetNode() method"""
78 node = self.dtb.GetNode('/spl-test')
79 self.assertTrue(isinstance(node, fdt.Node))
Simon Glasse44bc832019-07-20 12:23:39 -060080
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -060084 self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
Simon Glass2ba98752018-07-06 10:27:24 -060085
Simon Glasse44bc832019-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 Glass2ba98752018-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 Glass2ab6e132019-05-17 22:00:39 -060093 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-07-06 10:27:24 -060094 data = fd.read()
95 os.remove(fname)
96 with self.assertRaises(IOError):
Simon Glass2ab6e132019-05-17 22:00:39 -060097 open(fname, 'rb')
Simon Glass2ba98752018-07-06 10:27:24 -060098 self.dtb.Flush()
Simon Glass2ab6e132019-05-17 22:00:39 -060099 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-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 Glass96066242018-07-06 10:27:27 -0600108 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -0600115 'intarray', 'intval', 'longbytearray', 'notstring',
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -0600122 fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
Simon Glass2ba98752018-07-06 10:27:24 -0600123 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
124
Simon Glass94a7c602018-07-17 13:25:46 -0600125 def testGetFdt(self):
126 node = self.dtb.GetNode('/spl-test')
127 self.assertEqual(self.dtb, node.GetFdt())
Simon Glass2ba98752018-07-06 10:27:24 -0600128
Simon Glassb5f0daf2019-05-17 22:00:41 -0600129 def testBytesToValue(self):
130 self.assertEqual(BytesToValue(b'this\0is\0'),
131 (TYPE_STRING, ['this', 'is']))
132
Simon Glass2ba98752018-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 Glasse0e62752018-10-01 21:12:41 -0600142 tools.FinaliseOutputDir()
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -0600162 with self.assertRaises(libfdt.FdtException):
163 self.node.DeleteProp('missing')
Simon Glass2ba98752018-07-06 10:27:24 -0600164
Simon Glassf9b88b32018-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 Glass2ba98752018-07-06 10:27:24 -0600171 def testFindNode(self):
Simon Glass1d858882018-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 Glass2ba98752018-07-06 10:27:24 -0600174 self.assertEqual('i2c@0', node.name)
Simon Glass1d858882018-07-17 13:25:41 -0600175 subnode = node.FindNode('pmic@9')
Simon Glass2ba98752018-07-06 10:27:24 -0600176 self.assertEqual('pmic@9', subnode.name)
Simon Glass1d858882018-07-17 13:25:41 -0600177 self.assertEqual(None, node.FindNode('missing'))
Simon Glass2ba98752018-07-06 10:27:24 -0600178
Simon Glassf9b88b32018-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 Glass94a7c602018-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 Glass2ba98752018-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 Glasse0e62752018-10-01 21:12:41 -0600223 tools.FinaliseOutputDir()
Simon Glass2ba98752018-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 Glassb9066ff2018-07-06 10:27:30 -0600230 def testMissingNode(self):
231 self.assertEqual(None, self.dtb.GetNode('missing'))
232
Simon Glass2a2d91d2018-07-06 10:27:28 -0600233 def testPhandle(self):
234 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
Simon Glass760b7172018-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 Glass2a2d91d2018-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 Glass50c59522018-07-26 14:02:13 -0600247 p = self.fdt.getprop(self.node.Offset(), prop_name)
Simon Glass2a2d91d2018-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 Glass2ba98752018-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 Glass194b8d52019-05-17 22:00:33 -0600291 self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
Simon Glass2ba98752018-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 Glassf9b88b32018-07-06 10:27:29 -0600296 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
297 self.assertEqual(prop.value, value)
Simon Glass2ba98752018-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 Glass116adec2018-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 Glassfa80c252018-09-14 04:57:13 -0600351 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-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 Glassfa80c252018-09-14 04:57:13 -0600359 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600360
361 # This should fail since it would need to increase the device-tree size
Simon Glassfa80c252018-09-14 04:57:13 -0600362 self.node.AddZeroProp('four')
Simon Glass116adec2018-07-06 10:27:38 -0600363 with self.assertRaises(libfdt.FdtException) as e:
Simon Glassfa80c252018-09-14 04:57:13 -0600364 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600365 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
Simon Glass64349612018-09-14 04:57:16 -0600366 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-07-06 10:27:38 -0600367
Simon Glassfa80c252018-09-14 04:57:13 -0600368 def testAddNode(self):
369 self.fdt.pack()
Simon Glasse21c27a2018-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 Glassfa80c252018-09-14 04:57:13 -0600378
Simon Glass64349612018-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 Glassf6b64812019-05-17 22:00:36 -0600395 self.assertEqual(tools.ToBytes(val) + b'\0', data)
Simon Glass64349612018-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 Glassf6b64812019-05-17 22:00:36 -0600405 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600406 self.dtb.Sync(auto_resize=False)
407 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glassf6b64812019-05-17 22:00:36 -0600408 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-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 Glassf6b64812019-05-17 22:00:36 -0600413 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600414 self.dtb.Sync(auto_resize=False)
415 data = self.fdt.getprop(self.node.Offset(), 'empty')
Simon Glassf6b64812019-05-17 22:00:36 -0600416 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-09-14 04:57:16 -0600417
Simon Glassf6b64812019-05-17 22:00:36 -0600418 self.node.SetData('empty', b'123')
419 self.assertEqual(b'123', prop.bytes)
Simon Glass64349612018-09-14 04:57:16 -0600420
Simon Glass746aee32018-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 Glassd9dad102019-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 Glassf6e02492019-07-20 12:24:08 -0600450 def testGetFilename(self):
451 """Test the dtb filename can be provided"""
452 self.assertEqual(tools.GetOutputFilename('source.dtb'),
453 self.dtb.GetFilename())
454
Simon Glass2ba98752018-07-06 10:27:24 -0600455
Simon Glass2a2d91d2018-07-06 10:27:28 -0600456class TestFdtUtil(unittest.TestCase):
457 """Tests for the fdt_util module
458
459 This module will likely be mostly replaced at some point, once upstream
460 libfdt has better Python support. For now, this provides tests for current
461 functionality.
462 """
463 @classmethod
464 def setUpClass(cls):
465 tools.PrepareOutputDir(None)
466
Simon Glasse0e62752018-10-01 21:12:41 -0600467 @classmethod
468 def tearDownClass(cls):
469 tools.FinaliseOutputDir()
470
Simon Glass2a2d91d2018-07-06 10:27:28 -0600471 def setUp(self):
472 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
473 self.node = self.dtb.GetNode('/spl-test')
474
475 def testGetInt(self):
476 self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
477 self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
478
479 with self.assertRaises(ValueError) as e:
480 self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
481 self.assertIn("property 'intarray' has list value: expecting a single "
482 'integer', str(e.exception))
483
484 def testGetString(self):
485 self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
486 self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
487 'test'))
488
489 with self.assertRaises(ValueError) as e:
490 self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
491 self.assertIn("property 'stringarray' has list value: expecting a "
492 'single string', str(e.exception))
493
494 def testGetBool(self):
495 self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
496 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
497 self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
498 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
499
Simon Glass3af8e492018-07-17 13:25:40 -0600500 def testGetByte(self):
501 self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
502 self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
503
504 with self.assertRaises(ValueError) as e:
505 fdt_util.GetByte(self.node, 'longbytearray')
506 self.assertIn("property 'longbytearray' has list value: expecting a "
507 'single byte', str(e.exception))
508
509 with self.assertRaises(ValueError) as e:
510 fdt_util.GetByte(self.node, 'intval')
511 self.assertIn("property 'intval' has length 4, expecting 1",
512 str(e.exception))
513
Simon Glass94a7c602018-07-17 13:25:46 -0600514 def testGetPhandleList(self):
515 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
516 node = dtb.GetNode('/phandle-source2')
517 self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
518 node = dtb.GetNode('/phandle-source')
519 self.assertEqual([1, 2, 11, 3, 12, 13, 1],
520 fdt_util.GetPhandleList(node, 'clocks'))
521 self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
522
Simon Glass53af22a2018-07-17 13:25:32 -0600523 def testGetDataType(self):
524 self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
525 self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
526 str))
527 with self.assertRaises(ValueError) as e:
528 self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
529 bool))
Simon Glass2a2d91d2018-07-06 10:27:28 -0600530 def testFdtCellsToCpu(self):
531 val = self.node.props['intarray'].value
532 self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
533 self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
534
535 dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
Simon Glasse66d3182019-05-17 22:00:40 -0600536 node1 = dtb2.GetNode('/test1')
537 val = node1.props['reg'].value
Simon Glass2a2d91d2018-07-06 10:27:28 -0600538 self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
539
Simon Glasse66d3182019-05-17 22:00:40 -0600540 node2 = dtb2.GetNode('/test2')
541 val = node2.props['reg'].value
542 self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
543 self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
544 2))
545 self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
546
Simon Glass2a2d91d2018-07-06 10:27:28 -0600547 def testEnsureCompiled(self):
Simon Glassa004f292019-07-20 12:23:49 -0600548 """Test a degenerate case of this function (file already compiled)"""
Simon Glass2a2d91d2018-07-06 10:27:28 -0600549 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
550 self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
551
Simon Glassa004f292019-07-20 12:23:49 -0600552 def testEnsureCompiledTmpdir(self):
553 """Test providing a temporary directory"""
554 try:
555 old_outdir = tools.outdir
556 tools.outdir= None
557 tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
558 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts',
559 tmpdir)
560 self.assertEqual(tmpdir, os.path.dirname(dtb))
561 shutil.rmtree(tmpdir)
562 finally:
563 tools.outdir= old_outdir
564
Simon Glass2a2d91d2018-07-06 10:27:28 -0600565
566def RunTestCoverage():
567 """Run the tests and check that we get 100% coverage"""
568 test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
569 ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
570
571
Simon Glass2ba98752018-07-06 10:27:24 -0600572def RunTests(args):
573 """Run all the test we have for the fdt model
574
575 Args:
576 args: List of positional args provided to fdt. This can hold a test
577 name to execute (as in 'fdt -t testFdt', for example)
578 """
579 result = unittest.TestResult()
580 sys.argv = [sys.argv[0]]
581 test_name = args and args[0] or None
Simon Glass2a2d91d2018-07-06 10:27:28 -0600582 for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
Simon Glass2ba98752018-07-06 10:27:24 -0600583 if test_name:
584 try:
585 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
586 except AttributeError:
587 continue
588 else:
589 suite = unittest.TestLoader().loadTestsFromTestCase(module)
590 suite.run(result)
591
Simon Glass90a81322019-05-17 22:00:31 -0600592 print(result)
Simon Glass2ba98752018-07-06 10:27:24 -0600593 for _, err in result.errors:
Simon Glass90a81322019-05-17 22:00:31 -0600594 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600595 for _, err in result.failures:
Simon Glass90a81322019-05-17 22:00:31 -0600596 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600597
598if __name__ != '__main__':
599 sys.exit(1)
600
601parser = OptionParser()
Simon Glass2a2d91d2018-07-06 10:27:28 -0600602parser.add_option('-B', '--build-dir', type='string', default='b',
603 help='Directory containing the build output')
Simon Glass11ae93e2018-10-01 21:12:47 -0600604parser.add_option('-P', '--processes', type=int,
605 help='set number of processes to use for running tests')
Simon Glass2ba98752018-07-06 10:27:24 -0600606parser.add_option('-t', '--test', action='store_true', dest='test',
607 default=False, help='run tests')
Simon Glass2a2d91d2018-07-06 10:27:28 -0600608parser.add_option('-T', '--test-coverage', action='store_true',
609 default=False, help='run tests and check for 100% coverage')
Simon Glass2ba98752018-07-06 10:27:24 -0600610(options, args) = parser.parse_args()
611
612# Run our meagre tests
613if options.test:
614 RunTests(args)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600615elif options.test_coverage:
616 RunTestCoverage()