Merge tag 'v2021.04-rc5' into next
[platform/kernel/u-boot.git] / tools / dtoc / test_fdt.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: GPL-2.0+
3 # Copyright (c) 2018 Google, Inc
4 # Written by Simon Glass <sjg@chromium.org>
5 #
6
7 from optparse import OptionParser
8 import glob
9 import os
10 import shutil
11 import sys
12 import tempfile
13 import unittest
14
15 # Bring in the patman libraries
16 our_path = os.path.dirname(os.path.realpath(__file__))
17 sys.path.insert(1, os.path.join(our_path, '..'))
18
19 from dtoc import fdt
20 from dtoc import fdt_util
21 from dtoc.fdt_util import fdt32_to_cpu
22 from fdt import Type, BytesToValue
23 import libfdt
24 from patman import command
25 from patman import test_util
26 from patman import tools
27
28 def _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)]
49     return prop, [chr(x) for x in data]
50
51 def find_dtb_file(dts_fname):
52     """Locate a test file in the test/ directory
53
54     Args:
55         dts_fname (str): Filename to find, e.g. 'dtoc_test_simple.dts]
56
57     Returns:
58         str: Path to the test filename
59     """
60     return os.path.join('tools/dtoc/test', dts_fname)
61
62
63 class TestFdt(unittest.TestCase):
64     """Tests for the Fdt module
65
66     This includes unit tests for some functions and functional tests for the fdt
67     module.
68     """
69     @classmethod
70     def setUpClass(cls):
71         tools.PrepareOutputDir(None)
72
73     @classmethod
74     def tearDownClass(cls):
75         tools.FinaliseOutputDir()
76
77     def setUp(self):
78         self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
79
80     def testFdt(self):
81         """Test that we can open an Fdt"""
82         self.dtb.Scan()
83         root = self.dtb.GetRoot()
84         self.assertTrue(isinstance(root, fdt.Node))
85
86     def testGetNode(self):
87         """Test the GetNode() method"""
88         node = self.dtb.GetNode('/spl-test')
89         self.assertTrue(isinstance(node, fdt.Node))
90
91         node = self.dtb.GetNode('/i2c@0/pmic@9')
92         self.assertTrue(isinstance(node, fdt.Node))
93         self.assertEqual('pmic@9', node.name)
94         self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
95
96         node = self.dtb.GetNode('/')
97         self.assertTrue(isinstance(node, fdt.Node))
98         self.assertEqual(0, node.Offset())
99
100     def testFlush(self):
101         """Check that we can flush the device tree out to its file"""
102         fname = self.dtb._fname
103         with open(fname, 'rb') as fd:
104             data = fd.read()
105         os.remove(fname)
106         with self.assertRaises(IOError):
107             open(fname, 'rb')
108         self.dtb.Flush()
109         with open(fname, 'rb') as fd:
110             data = fd.read()
111
112     def testPack(self):
113         """Test that packing a device tree works"""
114         self.dtb.Pack()
115
116     def testGetFdt(self):
117         """Tetst that we can access the raw device-tree data"""
118         self.assertTrue(isinstance(self.dtb.GetContents(), bytearray))
119
120     def testGetProps(self):
121         """Tests obtaining a list of properties"""
122         node = self.dtb.GetNode('/spl-test')
123         props = self.dtb.GetProps(node)
124         self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
125                           'intarray', 'intval', 'longbytearray', 'notstring',
126                           'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
127                          sorted(props.keys()))
128
129     def testCheckError(self):
130         """Tests the ChecKError() function"""
131         with self.assertRaises(ValueError) as e:
132             fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
133         self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
134
135     def testGetFdt(self):
136         node = self.dtb.GetNode('/spl-test')
137         self.assertEqual(self.dtb, node.GetFdt())
138
139     def testBytesToValue(self):
140         self.assertEqual(BytesToValue(b'this\0is\0'),
141                          (Type.STRING, ['this', 'is']))
142
143 class TestNode(unittest.TestCase):
144     """Test operation of the Node class"""
145
146     @classmethod
147     def setUpClass(cls):
148         tools.PrepareOutputDir(None)
149
150     @classmethod
151     def tearDownClass(cls):
152         tools.FinaliseOutputDir()
153
154     def setUp(self):
155         self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
156         self.node = self.dtb.GetNode('/spl-test')
157         self.fdt = self.dtb.GetFdtObj()
158
159     def testOffset(self):
160         """Tests that we can obtain the offset of a node"""
161         self.assertTrue(self.node.Offset() > 0)
162
163     def testDelete(self):
164         """Tests that we can delete a property"""
165         node2 = self.dtb.GetNode('/spl-test2')
166         offset1 = node2.Offset()
167         self.node.DeleteProp('intval')
168         offset2 = node2.Offset()
169         self.assertTrue(offset2 < offset1)
170         self.node.DeleteProp('intarray')
171         offset3 = node2.Offset()
172         self.assertTrue(offset3 < offset2)
173         with self.assertRaises(libfdt.FdtException):
174             self.node.DeleteProp('missing')
175
176     def testDeleteGetOffset(self):
177         """Test that property offset update when properties are deleted"""
178         self.node.DeleteProp('intval')
179         prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
180         self.assertEqual(prop.value, value)
181
182     def testFindNode(self):
183         """Tests that we can find a node using the FindNode() functoin"""
184         node = self.dtb.GetRoot().FindNode('i2c@0')
185         self.assertEqual('i2c@0', node.name)
186         subnode = node.FindNode('pmic@9')
187         self.assertEqual('pmic@9', subnode.name)
188         self.assertEqual(None, node.FindNode('missing'))
189
190     def testRefreshMissingNode(self):
191         """Test refreshing offsets when an extra node is present in dtb"""
192         # Delete it from our tables, not the device tree
193         del self.dtb._root.subnodes[-1]
194         with self.assertRaises(ValueError) as e:
195             self.dtb.Refresh()
196         self.assertIn('Internal error, offset', str(e.exception))
197
198     def testRefreshExtraNode(self):
199         """Test refreshing offsets when an expected node is missing"""
200         # Delete it from the device tre, not our tables
201         self.fdt.del_node(self.node.Offset())
202         with self.assertRaises(ValueError) as e:
203             self.dtb.Refresh()
204         self.assertIn('Internal error, node name mismatch '
205                       'spl-test != spl-test2', str(e.exception))
206
207     def testRefreshMissingProp(self):
208         """Test refreshing offsets when an extra property is present in dtb"""
209         # Delete it from our tables, not the device tree
210         del self.node.props['notstring']
211         with self.assertRaises(ValueError) as e:
212             self.dtb.Refresh()
213         self.assertIn("Internal error, node '/spl-test' property 'notstring' missing, offset ",
214                       str(e.exception))
215
216     def testLookupPhandle(self):
217         """Test looking up a single phandle"""
218         dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
219         node = dtb.GetNode('/phandle-source2')
220         prop = node.props['clocks']
221         target = dtb.GetNode('/phandle-target')
222         self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
223
224     def testAddNodeSpace(self):
225         """Test adding a single node when out of space"""
226         self.fdt.pack()
227         self.node.AddSubnode('subnode')
228         with self.assertRaises(libfdt.FdtException) as e:
229             self.dtb.Sync(auto_resize=False)
230         self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
231
232         self.dtb.Sync(auto_resize=True)
233         offset = self.fdt.path_offset('/spl-test/subnode')
234         self.assertTrue(offset > 0)
235
236     def testAddNodes(self):
237         """Test adding various subnode and properies"""
238         node = self.dtb.GetNode('/i2c@0')
239
240         # Add one more node next to the pmic one
241         sn1 = node.AddSubnode('node-one')
242         sn1.AddInt('integer-a', 12)
243         sn1.AddInt('integer-b', 23)
244
245         # Sync so that everything is clean
246         self.dtb.Sync(auto_resize=True)
247
248         # Add two subnodes next to pmic and node-one
249         sn2 = node.AddSubnode('node-two')
250         sn2.AddInt('integer-2a', 34)
251         sn2.AddInt('integer-2b', 45)
252
253         sn3 = node.AddSubnode('node-three')
254         sn3.AddInt('integer-3', 123)
255
256         # Add a property to the node after i2c@0 to check that this is not
257         # disturbed by adding a subnode to i2c@0
258         orig_node = self.dtb.GetNode('/orig-node')
259         orig_node.AddInt('integer-4', 456)
260
261         # Add a property to the pmic node to check that pmic properties are not
262         # disturbed
263         pmic = self.dtb.GetNode('/i2c@0/pmic@9')
264         pmic.AddInt('integer-5', 567)
265
266         self.dtb.Sync(auto_resize=True)
267
268     def testRefreshNameMismatch(self):
269         """Test name mismatch when syncing nodes and properties"""
270         prop = self.node.AddInt('integer-a', 12)
271
272         wrong_offset = self.dtb.GetNode('/i2c@0')._offset
273         self.node._offset = wrong_offset
274         with self.assertRaises(ValueError) as e:
275             self.dtb.Sync()
276         self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
277                       str(e.exception))
278
279         with self.assertRaises(ValueError) as e:
280             self.node.Refresh(wrong_offset)
281         self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
282                       str(e.exception))
283
284
285 class TestProp(unittest.TestCase):
286     """Test operation of the Prop class"""
287
288     @classmethod
289     def setUpClass(cls):
290         tools.PrepareOutputDir(None)
291
292     @classmethod
293     def tearDownClass(cls):
294         tools.FinaliseOutputDir()
295
296     def setUp(self):
297         self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
298         self.node = self.dtb.GetNode('/spl-test')
299         self.fdt = self.dtb.GetFdtObj()
300
301     def testMissingNode(self):
302         self.assertEqual(None, self.dtb.GetNode('missing'))
303
304     def testPhandle(self):
305         dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
306         node = dtb.GetNode('/phandle-source2')
307         prop = node.props['clocks']
308         self.assertTrue(fdt32_to_cpu(prop.value) > 0)
309
310     def _ConvertProp(self, prop_name):
311         """Helper function to look up a property in self.node and return it
312
313         Args:
314             Property name to find
315
316         Return fdt.Prop object for this property
317         """
318         p = self.fdt.getprop(self.node.Offset(), prop_name)
319         return fdt.Prop(self.node, -1, prop_name, p)
320
321     def testMakeProp(self):
322         """Test we can convert all the the types that are supported"""
323         prop = self._ConvertProp('boolval')
324         self.assertEqual(Type.BOOL, prop.type)
325         self.assertEqual(True, prop.value)
326
327         prop = self._ConvertProp('intval')
328         self.assertEqual(Type.INT, prop.type)
329         self.assertEqual(1, fdt32_to_cpu(prop.value))
330
331         prop = self._ConvertProp('intarray')
332         self.assertEqual(Type.INT, prop.type)
333         val = [fdt32_to_cpu(val) for val in prop.value]
334         self.assertEqual([2, 3, 4], val)
335
336         prop = self._ConvertProp('byteval')
337         self.assertEqual(Type.BYTE, prop.type)
338         self.assertEqual(5, ord(prop.value))
339
340         prop = self._ConvertProp('longbytearray')
341         self.assertEqual(Type.BYTE, prop.type)
342         val = [ord(val) for val in prop.value]
343         self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
344
345         prop = self._ConvertProp('stringval')
346         self.assertEqual(Type.STRING, prop.type)
347         self.assertEqual('message', prop.value)
348
349         prop = self._ConvertProp('stringarray')
350         self.assertEqual(Type.STRING, prop.type)
351         self.assertEqual(['multi-word', 'message'], prop.value)
352
353         prop = self._ConvertProp('notstring')
354         self.assertEqual(Type.BYTE, prop.type)
355         val = [ord(val) for val in prop.value]
356         self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
357
358     def testGetEmpty(self):
359         """Tests the GetEmpty() function for the various supported types"""
360         self.assertEqual(True, fdt.Prop.GetEmpty(Type.BOOL))
361         self.assertEqual(chr(0), fdt.Prop.GetEmpty(Type.BYTE))
362         self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(Type.INT))
363         self.assertEqual('', fdt.Prop.GetEmpty(Type.STRING))
364
365     def testGetOffset(self):
366         """Test we can get the offset of a property"""
367         prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
368         self.assertEqual(prop.value, value)
369
370     def testWiden(self):
371         """Test widening of values"""
372         node2 = self.dtb.GetNode('/spl-test2')
373         node3 = self.dtb.GetNode('/spl-test3')
374         prop = self.node.props['intval']
375
376         # No action
377         prop2 = node2.props['intval']
378         prop.Widen(prop2)
379         self.assertEqual(Type.INT, prop.type)
380         self.assertEqual(1, fdt32_to_cpu(prop.value))
381
382         # Convert singla value to array
383         prop2 = self.node.props['intarray']
384         prop.Widen(prop2)
385         self.assertEqual(Type.INT, prop.type)
386         self.assertTrue(isinstance(prop.value, list))
387
388         # A 4-byte array looks like a single integer. When widened by a longer
389         # byte array, it should turn into an array.
390         prop = self.node.props['longbytearray']
391         prop2 = node2.props['longbytearray']
392         prop3 = node3.props['longbytearray']
393         self.assertFalse(isinstance(prop2.value, list))
394         self.assertEqual(4, len(prop2.value))
395         self.assertEqual(b'\x09\x0a\x0b\x0c', prop2.value)
396         prop2.Widen(prop)
397         self.assertTrue(isinstance(prop2.value, list))
398         self.assertEqual(9, len(prop2.value))
399         self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\0',
400                           '\0', '\0', '\0', '\0'], prop2.value)
401         prop3.Widen(prop)
402         self.assertTrue(isinstance(prop3.value, list))
403         self.assertEqual(9, len(prop3.value))
404         self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\x0d',
405                           '\x0e', '\x0f', '\x10', '\0'], prop3.value)
406
407         # Similarly for a string array
408         prop = self.node.props['stringval']
409         prop2 = node2.props['stringarray']
410         self.assertFalse(isinstance(prop.value, list))
411         self.assertEqual(7, len(prop.value))
412         prop.Widen(prop2)
413         self.assertTrue(isinstance(prop.value, list))
414         self.assertEqual(3, len(prop.value))
415
416         # Enlarging an existing array
417         prop = self.node.props['stringarray']
418         prop2 = node2.props['stringarray']
419         self.assertTrue(isinstance(prop.value, list))
420         self.assertEqual(2, len(prop.value))
421         prop.Widen(prop2)
422         self.assertTrue(isinstance(prop.value, list))
423         self.assertEqual(3, len(prop.value))
424
425     def testAdd(self):
426         """Test adding properties"""
427         self.fdt.pack()
428         # This function should automatically expand the device tree
429         self.node.AddZeroProp('one')
430         self.node.AddZeroProp('two')
431         self.node.AddZeroProp('three')
432         self.dtb.Sync(auto_resize=True)
433
434         # Updating existing properties should be OK, since the device-tree size
435         # does not change
436         self.fdt.pack()
437         self.node.SetInt('one', 1)
438         self.node.SetInt('two', 2)
439         self.node.SetInt('three', 3)
440         self.dtb.Sync(auto_resize=False)
441
442         # This should fail since it would need to increase the device-tree size
443         self.node.AddZeroProp('four')
444         with self.assertRaises(libfdt.FdtException) as e:
445             self.dtb.Sync(auto_resize=False)
446         self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
447         self.dtb.Sync(auto_resize=True)
448
449     def testAddMore(self):
450         """Test various other methods for adding and setting properties"""
451         self.node.AddZeroProp('one')
452         self.dtb.Sync(auto_resize=True)
453         data = self.fdt.getprop(self.node.Offset(), 'one')
454         self.assertEqual(0, fdt32_to_cpu(data))
455
456         self.node.SetInt('one', 1)
457         self.dtb.Sync(auto_resize=False)
458         data = self.fdt.getprop(self.node.Offset(), 'one')
459         self.assertEqual(1, fdt32_to_cpu(data))
460
461         val = 1234
462         self.node.AddInt('integer', val)
463         self.dtb.Sync(auto_resize=True)
464         data = self.fdt.getprop(self.node.Offset(), 'integer')
465         self.assertEqual(val, fdt32_to_cpu(data))
466
467         val = '123' + chr(0) + '456'
468         self.node.AddString('string', val)
469         self.dtb.Sync(auto_resize=True)
470         data = self.fdt.getprop(self.node.Offset(), 'string')
471         self.assertEqual(tools.ToBytes(val) + b'\0', data)
472
473         self.fdt.pack()
474         self.node.SetString('string', val + 'x')
475         with self.assertRaises(libfdt.FdtException) as e:
476             self.dtb.Sync(auto_resize=False)
477         self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
478         self.node.SetString('string', val[:-1])
479
480         prop = self.node.props['string']
481         prop.SetData(tools.ToBytes(val))
482         self.dtb.Sync(auto_resize=False)
483         data = self.fdt.getprop(self.node.Offset(), 'string')
484         self.assertEqual(tools.ToBytes(val), data)
485
486         self.node.AddEmptyProp('empty', 5)
487         self.dtb.Sync(auto_resize=True)
488         prop = self.node.props['empty']
489         prop.SetData(tools.ToBytes(val))
490         self.dtb.Sync(auto_resize=False)
491         data = self.fdt.getprop(self.node.Offset(), 'empty')
492         self.assertEqual(tools.ToBytes(val), data)
493
494         self.node.SetData('empty', b'123')
495         self.assertEqual(b'123', prop.bytes)
496
497         # Trying adding a lot of data at once
498         self.node.AddData('data', tools.GetBytes(65, 20000))
499         self.dtb.Sync(auto_resize=True)
500
501     def testFromData(self):
502         dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
503         self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
504
505         self.node.AddEmptyProp('empty', 5)
506         self.dtb.Sync(auto_resize=True)
507         self.assertTrue(dtb2.GetContents() != self.dtb.GetContents())
508
509     def testMissingSetInt(self):
510         """Test handling of a missing property with SetInt"""
511         with self.assertRaises(ValueError) as e:
512             self.node.SetInt('one', 1)
513         self.assertIn("node '/spl-test': Missing property 'one'",
514                       str(e.exception))
515
516     def testMissingSetData(self):
517         """Test handling of a missing property with SetData"""
518         with self.assertRaises(ValueError) as e:
519             self.node.SetData('one', b'data')
520         self.assertIn("node '/spl-test': Missing property 'one'",
521                       str(e.exception))
522
523     def testMissingSetString(self):
524         """Test handling of a missing property with SetString"""
525         with self.assertRaises(ValueError) as e:
526             self.node.SetString('one', 1)
527         self.assertIn("node '/spl-test': Missing property 'one'",
528                       str(e.exception))
529
530     def testGetFilename(self):
531         """Test the dtb filename can be provided"""
532         self.assertEqual(tools.GetOutputFilename('source.dtb'),
533                          self.dtb.GetFilename())
534
535
536 class TestFdtUtil(unittest.TestCase):
537     """Tests for the fdt_util module
538
539     This module will likely be mostly replaced at some point, once upstream
540     libfdt has better Python support. For now, this provides tests for current
541     functionality.
542     """
543     @classmethod
544     def setUpClass(cls):
545         tools.PrepareOutputDir(None)
546
547     @classmethod
548     def tearDownClass(cls):
549         tools.FinaliseOutputDir()
550
551     def setUp(self):
552         self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
553         self.node = self.dtb.GetNode('/spl-test')
554
555     def testGetInt(self):
556         self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
557         self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
558
559         with self.assertRaises(ValueError) as e:
560             self.assertEqual(3, fdt_util.GetInt(self.node, 'intarray'))
561         self.assertIn("property 'intarray' has list value: expecting a single "
562                       'integer', str(e.exception))
563
564     def testGetString(self):
565         self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
566         self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
567                                                     'test'))
568
569         with self.assertRaises(ValueError) as e:
570             self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
571         self.assertIn("property 'stringarray' has list value: expecting a "
572                       'single string', str(e.exception))
573
574     def testGetBool(self):
575         self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
576         self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
577         self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
578         self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
579
580     def testGetByte(self):
581         self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
582         self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
583
584         with self.assertRaises(ValueError) as e:
585             fdt_util.GetByte(self.node, 'longbytearray')
586         self.assertIn("property 'longbytearray' has list value: expecting a "
587                       'single byte', str(e.exception))
588
589         with self.assertRaises(ValueError) as e:
590             fdt_util.GetByte(self.node, 'intval')
591         self.assertIn("property 'intval' has length 4, expecting 1",
592                       str(e.exception))
593
594     def testGetPhandleList(self):
595         dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
596         node = dtb.GetNode('/phandle-source2')
597         self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
598         node = dtb.GetNode('/phandle-source')
599         self.assertEqual([1, 2, 11, 3, 12, 13, 1],
600                          fdt_util.GetPhandleList(node, 'clocks'))
601         self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
602
603     def testGetDataType(self):
604         self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
605         self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
606                                                          str))
607         with self.assertRaises(ValueError) as e:
608             self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
609                                                      bool))
610     def testFdtCellsToCpu(self):
611         val = self.node.props['intarray'].value
612         self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
613         self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
614
615         dtb2 = fdt.FdtScan(find_dtb_file('dtoc_test_addr64.dts'))
616         node1 = dtb2.GetNode('/test1')
617         val = node1.props['reg'].value
618         self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
619
620         node2 = dtb2.GetNode('/test2')
621         val = node2.props['reg'].value
622         self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
623         self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
624                                                                        2))
625         self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
626
627     def testEnsureCompiled(self):
628         """Test a degenerate case of this function (file already compiled)"""
629         dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'))
630         self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
631
632     def testEnsureCompiledTmpdir(self):
633         """Test providing a temporary directory"""
634         try:
635             old_outdir = tools.outdir
636             tools.outdir= None
637             tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
638             dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'),
639                                           tmpdir)
640             self.assertEqual(tmpdir, os.path.dirname(dtb))
641             shutil.rmtree(tmpdir)
642         finally:
643             tools.outdir= old_outdir
644
645
646 def RunTestCoverage():
647     """Run the tests and check that we get 100% coverage"""
648     test_util.RunTestCoverage('tools/dtoc/test_fdt.py', None,
649             ['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
650
651
652 def RunTests(args):
653     """Run all the test we have for the fdt model
654
655     Args:
656         args: List of positional args provided to fdt. This can hold a test
657             name to execute (as in 'fdt -t testFdt', for example)
658     """
659     result = unittest.TestResult()
660     sys.argv = [sys.argv[0]]
661     test_name = args and args[0] or None
662     for module in (TestFdt, TestNode, TestProp, TestFdtUtil):
663         if test_name:
664             try:
665                 suite = unittest.TestLoader().loadTestsFromName(test_name, module)
666             except AttributeError:
667                 continue
668         else:
669             suite = unittest.TestLoader().loadTestsFromTestCase(module)
670         suite.run(result)
671
672     print(result)
673     for _, err in result.errors:
674         print(err)
675     for _, err in result.failures:
676         print(err)
677
678 if __name__ != '__main__':
679     sys.exit(1)
680
681 parser = OptionParser()
682 parser.add_option('-B', '--build-dir', type='string', default='b',
683         help='Directory containing the build output')
684 parser.add_option('-P', '--processes', type=int,
685                   help='set number of processes to use for running tests')
686 parser.add_option('-t', '--test', action='store_true', dest='test',
687                   default=False, help='run tests')
688 parser.add_option('-T', '--test-coverage', action='store_true',
689                 default=False, help='run tests and check for 100% coverage')
690 (options, args) = parser.parse_args()
691
692 # Run our meagre tests
693 if options.test:
694     RunTests(args)
695 elif options.test_coverage:
696     RunTestCoverage()