blob: b4f9b7f498fa23e66443ffcd5e5834273d1fb579 [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__))
Simon Glassb4fa9492020-04-17 18:09:05 -060017sys.path.insert(1, os.path.join(our_path, '..'))
Simon Glass2ba98752018-07-06 10:27:24 -060018
Simon Glassbf776672020-04-17 18:09:04 -060019from dtoc import fdt
20from dtoc import fdt_util
21from dtoc.fdt_util import fdt32_to_cpu
Simon Glassb5f0daf2019-05-17 22:00:41 -060022from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
Simon Glass2ba98752018-07-06 10:27:24 -060023import libfdt
Simon Glassbf776672020-04-17 18:09:04 -060024from patman import command
25from patman import test_util
26from patman import tools
Simon Glass2ba98752018-07-06 10:27:24 -060027
Simon Glassf9b88b32018-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 Glassf6b64812019-05-17 22:00:36 -060049 return prop, [tools.ToChar(x) for x in data]
Simon Glassf9b88b32018-07-06 10:27:29 -060050
51
Simon Glass2ba98752018-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 Glasse0e62752018-10-01 21:12:41 -060064 tools.FinaliseOutputDir()
Simon Glass2ba98752018-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 Glasse44bc832019-07-20 12:23:39 -060079
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -060083 self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
Simon Glass2ba98752018-07-06 10:27:24 -060084
Simon Glasse44bc832019-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 Glass2ba98752018-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 Glass2ab6e132019-05-17 22:00:39 -060092 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-07-06 10:27:24 -060093 data = fd.read()
94 os.remove(fname)
95 with self.assertRaises(IOError):
Simon Glass2ab6e132019-05-17 22:00:39 -060096 open(fname, 'rb')
Simon Glass2ba98752018-07-06 10:27:24 -060097 self.dtb.Flush()
Simon Glass2ab6e132019-05-17 22:00:39 -060098 with open(fname, 'rb') as fd:
Simon Glass2ba98752018-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 Glass96066242018-07-06 10:27:27 -0600107 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -0600114 'intarray', 'intval', 'longbytearray', 'notstring',
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -0600121 fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
Simon Glass2ba98752018-07-06 10:27:24 -0600122 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
123
Simon Glass94a7c602018-07-17 13:25:46 -0600124 def testGetFdt(self):
125 node = self.dtb.GetNode('/spl-test')
126 self.assertEqual(self.dtb, node.GetFdt())
Simon Glass2ba98752018-07-06 10:27:24 -0600127
Simon Glassb5f0daf2019-05-17 22:00:41 -0600128 def testBytesToValue(self):
129 self.assertEqual(BytesToValue(b'this\0is\0'),
130 (TYPE_STRING, ['this', 'is']))
131
Simon Glass2ba98752018-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 Glasse0e62752018-10-01 21:12:41 -0600141 tools.FinaliseOutputDir()
Simon Glass2ba98752018-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 Glass2a2d91d2018-07-06 10:27:28 -0600161 with self.assertRaises(libfdt.FdtException):
162 self.node.DeleteProp('missing')
Simon Glass2ba98752018-07-06 10:27:24 -0600163
Simon Glassf9b88b32018-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 Glass2ba98752018-07-06 10:27:24 -0600170 def testFindNode(self):
Simon Glass1d858882018-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 Glass2ba98752018-07-06 10:27:24 -0600173 self.assertEqual('i2c@0', node.name)
Simon Glass1d858882018-07-17 13:25:41 -0600174 subnode = node.FindNode('pmic@9')
Simon Glass2ba98752018-07-06 10:27:24 -0600175 self.assertEqual('pmic@9', subnode.name)
Simon Glass1d858882018-07-17 13:25:41 -0600176 self.assertEqual(None, node.FindNode('missing'))
Simon Glass2ba98752018-07-06 10:27:24 -0600177
Simon Glassf9b88b32018-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 Glass94a7c602018-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 Glass2ba98752018-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 Glasse0e62752018-10-01 21:12:41 -0600222 tools.FinaliseOutputDir()
Simon Glass2ba98752018-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 Glassb9066ff2018-07-06 10:27:30 -0600229 def testMissingNode(self):
230 self.assertEqual(None, self.dtb.GetNode('missing'))
231
Simon Glass2a2d91d2018-07-06 10:27:28 -0600232 def testPhandle(self):
233 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
Simon Glass760b7172018-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 Glass2a2d91d2018-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 Glass50c59522018-07-26 14:02:13 -0600246 p = self.fdt.getprop(self.node.Offset(), prop_name)
Simon Glass2a2d91d2018-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')
252 self.assertEqual(fdt.TYPE_BOOL, prop.type)
253 self.assertEqual(True, prop.value)
254
255 prop = self._ConvertProp('intval')
256 self.assertEqual(fdt.TYPE_INT, prop.type)
257 self.assertEqual(1, fdt32_to_cpu(prop.value))
258
259 prop = self._ConvertProp('intarray')
260 self.assertEqual(fdt.TYPE_INT, prop.type)
261 val = [fdt32_to_cpu(val) for val in prop.value]
262 self.assertEqual([2, 3, 4], val)
263
264 prop = self._ConvertProp('byteval')
265 self.assertEqual(fdt.TYPE_BYTE, prop.type)
266 self.assertEqual(5, ord(prop.value))
267
268 prop = self._ConvertProp('longbytearray')
269 self.assertEqual(fdt.TYPE_BYTE, prop.type)
270 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')
274 self.assertEqual(fdt.TYPE_STRING, prop.type)
275 self.assertEqual('message', prop.value)
276
277 prop = self._ConvertProp('stringarray')
278 self.assertEqual(fdt.TYPE_STRING, prop.type)
279 self.assertEqual(['multi-word', 'message'], prop.value)
280
281 prop = self._ConvertProp('notstring')
282 self.assertEqual(fdt.TYPE_BYTE, prop.type)
283 val = [ord(val) for val in prop.value]
284 self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
285
Simon Glass2ba98752018-07-06 10:27:24 -0600286 def testGetEmpty(self):
287 """Tests the GetEmpty() function for the various supported types"""
288 self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
289 self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
Simon Glass194b8d52019-05-17 22:00:33 -0600290 self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
Simon Glass2ba98752018-07-06 10:27:24 -0600291 self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
292
293 def testGetOffset(self):
294 """Test we can get the offset of a property"""
Simon Glassf9b88b32018-07-06 10:27:29 -0600295 prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
296 self.assertEqual(prop.value, value)
Simon Glass2ba98752018-07-06 10:27:24 -0600297
298 def testWiden(self):
299 """Test widening of values"""
300 node2 = self.dtb.GetNode('/spl-test2')
301 prop = self.node.props['intval']
302
303 # No action
304 prop2 = node2.props['intval']
305 prop.Widen(prop2)
306 self.assertEqual(fdt.TYPE_INT, prop.type)
307 self.assertEqual(1, fdt32_to_cpu(prop.value))
308
309 # Convert singla value to array
310 prop2 = self.node.props['intarray']
311 prop.Widen(prop2)
312 self.assertEqual(fdt.TYPE_INT, prop.type)
313 self.assertTrue(isinstance(prop.value, list))
314
315 # A 4-byte array looks like a single integer. When widened by a longer
316 # byte array, it should turn into an array.
317 prop = self.node.props['longbytearray']
318 prop2 = node2.props['longbytearray']
319 self.assertFalse(isinstance(prop2.value, list))
320 self.assertEqual(4, len(prop2.value))
321 prop2.Widen(prop)
322 self.assertTrue(isinstance(prop2.value, list))
323 self.assertEqual(9, len(prop2.value))
324
325 # Similarly for a string array
326 prop = self.node.props['stringval']
327 prop2 = node2.props['stringarray']
328 self.assertFalse(isinstance(prop.value, list))
329 self.assertEqual(7, len(prop.value))
330 prop.Widen(prop2)
331 self.assertTrue(isinstance(prop.value, list))
332 self.assertEqual(3, len(prop.value))
333
334 # Enlarging an existing array
335 prop = self.node.props['stringarray']
336 prop2 = node2.props['stringarray']
337 self.assertTrue(isinstance(prop.value, list))
338 self.assertEqual(2, len(prop.value))
339 prop.Widen(prop2)
340 self.assertTrue(isinstance(prop.value, list))
341 self.assertEqual(3, len(prop.value))
342
Simon Glass116adec2018-07-06 10:27:38 -0600343 def testAdd(self):
344 """Test adding properties"""
345 self.fdt.pack()
346 # This function should automatically expand the device tree
347 self.node.AddZeroProp('one')
348 self.node.AddZeroProp('two')
349 self.node.AddZeroProp('three')
Simon Glassfa80c252018-09-14 04:57:13 -0600350 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-07-06 10:27:38 -0600351
352 # Updating existing properties should be OK, since the device-tree size
353 # does not change
354 self.fdt.pack()
355 self.node.SetInt('one', 1)
356 self.node.SetInt('two', 2)
357 self.node.SetInt('three', 3)
Simon Glassfa80c252018-09-14 04:57:13 -0600358 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600359
360 # This should fail since it would need to increase the device-tree size
Simon Glassfa80c252018-09-14 04:57:13 -0600361 self.node.AddZeroProp('four')
Simon Glass116adec2018-07-06 10:27:38 -0600362 with self.assertRaises(libfdt.FdtException) as e:
Simon Glassfa80c252018-09-14 04:57:13 -0600363 self.dtb.Sync(auto_resize=False)
Simon Glass116adec2018-07-06 10:27:38 -0600364 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
Simon Glass64349612018-09-14 04:57:16 -0600365 self.dtb.Sync(auto_resize=True)
Simon Glass116adec2018-07-06 10:27:38 -0600366
Simon Glassfa80c252018-09-14 04:57:13 -0600367 def testAddNode(self):
368 self.fdt.pack()
Simon Glasse21c27a2018-09-14 04:57:15 -0600369 self.node.AddSubnode('subnode')
370 with self.assertRaises(libfdt.FdtException) as e:
371 self.dtb.Sync(auto_resize=False)
372 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
373
374 self.dtb.Sync(auto_resize=True)
375 offset = self.fdt.path_offset('/spl-test/subnode')
376 self.assertTrue(offset > 0)
Simon Glassfa80c252018-09-14 04:57:13 -0600377
Simon Glass64349612018-09-14 04:57:16 -0600378 def testAddMore(self):
379 """Test various other methods for adding and setting properties"""
380 self.node.AddZeroProp('one')
381 self.dtb.Sync(auto_resize=True)
382 data = self.fdt.getprop(self.node.Offset(), 'one')
383 self.assertEqual(0, fdt32_to_cpu(data))
384
385 self.node.SetInt('one', 1)
386 self.dtb.Sync(auto_resize=False)
387 data = self.fdt.getprop(self.node.Offset(), 'one')
388 self.assertEqual(1, fdt32_to_cpu(data))
389
390 val = '123' + chr(0) + '456'
391 self.node.AddString('string', val)
392 self.dtb.Sync(auto_resize=True)
393 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glassf6b64812019-05-17 22:00:36 -0600394 self.assertEqual(tools.ToBytes(val) + b'\0', data)
Simon Glass64349612018-09-14 04:57:16 -0600395
396 self.fdt.pack()
397 self.node.SetString('string', val + 'x')
398 with self.assertRaises(libfdt.FdtException) as e:
399 self.dtb.Sync(auto_resize=False)
400 self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
401 self.node.SetString('string', val[:-1])
402
403 prop = self.node.props['string']
Simon Glassf6b64812019-05-17 22:00:36 -0600404 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600405 self.dtb.Sync(auto_resize=False)
406 data = self.fdt.getprop(self.node.Offset(), 'string')
Simon Glassf6b64812019-05-17 22:00:36 -0600407 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-09-14 04:57:16 -0600408
409 self.node.AddEmptyProp('empty', 5)
410 self.dtb.Sync(auto_resize=True)
411 prop = self.node.props['empty']
Simon Glassf6b64812019-05-17 22:00:36 -0600412 prop.SetData(tools.ToBytes(val))
Simon Glass64349612018-09-14 04:57:16 -0600413 self.dtb.Sync(auto_resize=False)
414 data = self.fdt.getprop(self.node.Offset(), 'empty')
Simon Glassf6b64812019-05-17 22:00:36 -0600415 self.assertEqual(tools.ToBytes(val), data)
Simon Glass64349612018-09-14 04:57:16 -0600416
Simon Glassf6b64812019-05-17 22:00:36 -0600417 self.node.SetData('empty', b'123')
418 self.assertEqual(b'123', prop.bytes)
Simon Glass64349612018-09-14 04:57:16 -0600419
Simon Glass1f238bd2020-07-09 18:39:44 -0600420 # Trying adding a lot of data at once
421 self.node.AddData('data', tools.GetBytes(65, 20000))
422 self.dtb.Sync(auto_resize=True)
423
Simon Glass746aee32018-09-14 04:57:17 -0600424 def testFromData(self):
425 dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
426 self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
427
428 self.node.AddEmptyProp('empty', 5)
429 self.dtb.Sync(auto_resize=True)
430 self.assertTrue(dtb2.GetContents() != self.dtb.GetContents())
431
Simon Glassd9dad102019-07-20 12:23:37 -0600432 def testMissingSetInt(self):
433 """Test handling of a missing property with SetInt"""
434 with self.assertRaises(ValueError) as e:
435 self.node.SetInt('one', 1)
436 self.assertIn("node '/spl-test': Missing property 'one'",
437 str(e.exception))
438
439 def testMissingSetData(self):
440 """Test handling of a missing property with SetData"""
441 with self.assertRaises(ValueError) as e:
442 self.node.SetData('one', b'data')
443 self.assertIn("node '/spl-test': Missing property 'one'",
444 str(e.exception))
445
446 def testMissingSetString(self):
447 """Test handling of a missing property with SetString"""
448 with self.assertRaises(ValueError) as e:
449 self.node.SetString('one', 1)
450 self.assertIn("node '/spl-test': Missing property 'one'",
451 str(e.exception))
452
Simon Glassf6e02492019-07-20 12:24:08 -0600453 def testGetFilename(self):
454 """Test the dtb filename can be provided"""
455 self.assertEqual(tools.GetOutputFilename('source.dtb'),
456 self.dtb.GetFilename())
457
Simon Glass2ba98752018-07-06 10:27:24 -0600458
Simon Glass2a2d91d2018-07-06 10:27:28 -0600459class TestFdtUtil(unittest.TestCase):
460 """Tests for the fdt_util module
461
462 This module will likely be mostly replaced at some point, once upstream
463 libfdt has better Python support. For now, this provides tests for current
464 functionality.
465 """
466 @classmethod
467 def setUpClass(cls):
468 tools.PrepareOutputDir(None)
469
Simon Glasse0e62752018-10-01 21:12:41 -0600470 @classmethod
471 def tearDownClass(cls):
472 tools.FinaliseOutputDir()
473
Simon Glass2a2d91d2018-07-06 10:27:28 -0600474 def setUp(self):
475 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
476 self.node = self.dtb.GetNode('/spl-test')
477
478 def testGetInt(self):
479 self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
480 self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
481
482 with self.assertRaises(ValueError) as e:
483 self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
484 self.assertIn("property 'intarray' has list value: expecting a single "
485 'integer', str(e.exception))
486
487 def testGetString(self):
488 self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
489 self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
490 'test'))
491
492 with self.assertRaises(ValueError) as e:
493 self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
494 self.assertIn("property 'stringarray' has list value: expecting a "
495 'single string', str(e.exception))
496
497 def testGetBool(self):
498 self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
499 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
500 self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
501 self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
502
Simon Glass3af8e492018-07-17 13:25:40 -0600503 def testGetByte(self):
504 self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
505 self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
506
507 with self.assertRaises(ValueError) as e:
508 fdt_util.GetByte(self.node, 'longbytearray')
509 self.assertIn("property 'longbytearray' has list value: expecting a "
510 'single byte', str(e.exception))
511
512 with self.assertRaises(ValueError) as e:
513 fdt_util.GetByte(self.node, 'intval')
514 self.assertIn("property 'intval' has length 4, expecting 1",
515 str(e.exception))
516
Simon Glass94a7c602018-07-17 13:25:46 -0600517 def testGetPhandleList(self):
518 dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
519 node = dtb.GetNode('/phandle-source2')
520 self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
521 node = dtb.GetNode('/phandle-source')
522 self.assertEqual([1, 2, 11, 3, 12, 13, 1],
523 fdt_util.GetPhandleList(node, 'clocks'))
524 self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
525
Simon Glass53af22a2018-07-17 13:25:32 -0600526 def testGetDataType(self):
527 self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
528 self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
529 str))
530 with self.assertRaises(ValueError) as e:
531 self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
532 bool))
Simon Glass2a2d91d2018-07-06 10:27:28 -0600533 def testFdtCellsToCpu(self):
534 val = self.node.props['intarray'].value
535 self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
536 self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
537
538 dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
Simon Glasse66d3182019-05-17 22:00:40 -0600539 node1 = dtb2.GetNode('/test1')
540 val = node1.props['reg'].value
Simon Glass2a2d91d2018-07-06 10:27:28 -0600541 self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
542
Simon Glasse66d3182019-05-17 22:00:40 -0600543 node2 = dtb2.GetNode('/test2')
544 val = node2.props['reg'].value
545 self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
546 self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
547 2))
548 self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
549
Simon Glass2a2d91d2018-07-06 10:27:28 -0600550 def testEnsureCompiled(self):
Simon Glassa004f292019-07-20 12:23:49 -0600551 """Test a degenerate case of this function (file already compiled)"""
Simon Glass2a2d91d2018-07-06 10:27:28 -0600552 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
553 self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
554
Simon Glassa004f292019-07-20 12:23:49 -0600555 def testEnsureCompiledTmpdir(self):
556 """Test providing a temporary directory"""
557 try:
558 old_outdir = tools.outdir
559 tools.outdir= None
560 tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
561 dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts',
562 tmpdir)
563 self.assertEqual(tmpdir, os.path.dirname(dtb))
564 shutil.rmtree(tmpdir)
565 finally:
566 tools.outdir= old_outdir
567
Simon Glass2a2d91d2018-07-06 10:27:28 -0600568
569def RunTestCoverage():
570 """Run the tests and check that we get 100% coverage"""
571 test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
572 ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
573
574
Simon Glass2ba98752018-07-06 10:27:24 -0600575def RunTests(args):
576 """Run all the test we have for the fdt model
577
578 Args:
579 args: List of positional args provided to fdt. This can hold a test
580 name to execute (as in 'fdt -t testFdt', for example)
581 """
582 result = unittest.TestResult()
583 sys.argv = [sys.argv[0]]
584 test_name = args and args[0] or None
Simon Glass2a2d91d2018-07-06 10:27:28 -0600585 for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
Simon Glass2ba98752018-07-06 10:27:24 -0600586 if test_name:
587 try:
588 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
589 except AttributeError:
590 continue
591 else:
592 suite = unittest.TestLoader().loadTestsFromTestCase(module)
593 suite.run(result)
594
Simon Glass90a81322019-05-17 22:00:31 -0600595 print(result)
Simon Glass2ba98752018-07-06 10:27:24 -0600596 for _, err in result.errors:
Simon Glass90a81322019-05-17 22:00:31 -0600597 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600598 for _, err in result.failures:
Simon Glass90a81322019-05-17 22:00:31 -0600599 print(err)
Simon Glass2ba98752018-07-06 10:27:24 -0600600
601if __name__ != '__main__':
602 sys.exit(1)
603
604parser = OptionParser()
Simon Glass2a2d91d2018-07-06 10:27:28 -0600605parser.add_option('-B', '--build-dir', type='string', default='b',
606 help='Directory containing the build output')
Simon Glass11ae93e2018-10-01 21:12:47 -0600607parser.add_option('-P', '--processes', type=int,
608 help='set number of processes to use for running tests')
Simon Glass2ba98752018-07-06 10:27:24 -0600609parser.add_option('-t', '--test', action='store_true', dest='test',
610 default=False, help='run tests')
Simon Glass2a2d91d2018-07-06 10:27:28 -0600611parser.add_option('-T', '--test-coverage', action='store_true',
612 default=False, help='run tests and check for 100% coverage')
Simon Glass2ba98752018-07-06 10:27:24 -0600613(options, args) = parser.parse_args()
614
615# Run our meagre tests
616if options.test:
617 RunTests(args)
Simon Glass2a2d91d2018-07-06 10:27:28 -0600618elif options.test_coverage:
619 RunTestCoverage()