test_fdt.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #!/usr/bin/python
  2. # SPDX-License-Identifier: GPL-2.0+
  3. # Copyright (c) 2018 Google, Inc
  4. # Written by Simon Glass <sjg@chromium.org>
  5. #
  6. from optparse import OptionParser
  7. import glob
  8. import os
  9. import sys
  10. import unittest
  11. # Bring in the patman libraries
  12. our_path = os.path.dirname(os.path.realpath(__file__))
  13. for dirname in ['../patman', '..']:
  14. sys.path.insert(0, os.path.join(our_path, dirname))
  15. import command
  16. import fdt
  17. from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL
  18. from fdt_util import fdt32_to_cpu
  19. import libfdt
  20. import test_util
  21. import tools
  22. class TestFdt(unittest.TestCase):
  23. """Tests for the Fdt module
  24. This includes unit tests for some functions and functional tests for the fdt
  25. module.
  26. """
  27. @classmethod
  28. def setUpClass(cls):
  29. tools.PrepareOutputDir(None)
  30. @classmethod
  31. def tearDownClass(cls):
  32. tools._FinaliseForTest()
  33. def setUp(self):
  34. self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
  35. def testFdt(self):
  36. """Test that we can open an Fdt"""
  37. self.dtb.Scan()
  38. root = self.dtb.GetRoot()
  39. self.assertTrue(isinstance(root, fdt.Node))
  40. def testGetNode(self):
  41. """Test the GetNode() method"""
  42. node = self.dtb.GetNode('/spl-test')
  43. self.assertTrue(isinstance(node, fdt.Node))
  44. node = self.dtb.GetNode('/i2c@0/pmic@9')
  45. self.assertTrue(isinstance(node, fdt.Node))
  46. self.assertEqual('pmic@9', node.name)
  47. def testFlush(self):
  48. """Check that we can flush the device tree out to its file"""
  49. fname = self.dtb._fname
  50. with open(fname) as fd:
  51. data = fd.read()
  52. os.remove(fname)
  53. with self.assertRaises(IOError):
  54. open(fname)
  55. self.dtb.Flush()
  56. with open(fname) as fd:
  57. data = fd.read()
  58. def testPack(self):
  59. """Test that packing a device tree works"""
  60. self.dtb.Pack()
  61. def testGetFdt(self):
  62. """Tetst that we can access the raw device-tree data"""
  63. self.assertTrue(isinstance(self.dtb.GetFdt(), bytearray))
  64. def testGetProps(self):
  65. """Tests obtaining a list of properties"""
  66. node = self.dtb.GetNode('/spl-test')
  67. props = self.dtb.GetProps(node)
  68. self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
  69. 'intarray', 'intval', 'longbytearray',
  70. 'stringarray', 'stringval', 'u-boot,dm-pre-reloc'],
  71. sorted(props.keys()))
  72. def testCheckError(self):
  73. """Tests the ChecKError() function"""
  74. with self.assertRaises(ValueError) as e:
  75. self.dtb.CheckErr(-libfdt.NOTFOUND, 'hello')
  76. self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
  77. class TestNode(unittest.TestCase):
  78. """Test operation of the Node class"""
  79. @classmethod
  80. def setUpClass(cls):
  81. tools.PrepareOutputDir(None)
  82. @classmethod
  83. def tearDownClass(cls):
  84. tools._FinaliseForTest()
  85. def setUp(self):
  86. self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
  87. self.node = self.dtb.GetNode('/spl-test')
  88. def testOffset(self):
  89. """Tests that we can obtain the offset of a node"""
  90. self.assertTrue(self.node.Offset() > 0)
  91. def testDelete(self):
  92. """Tests that we can delete a property"""
  93. node2 = self.dtb.GetNode('/spl-test2')
  94. offset1 = node2.Offset()
  95. self.node.DeleteProp('intval')
  96. offset2 = node2.Offset()
  97. self.assertTrue(offset2 < offset1)
  98. self.node.DeleteProp('intarray')
  99. offset3 = node2.Offset()
  100. self.assertTrue(offset3 < offset2)
  101. def testFindNode(self):
  102. """Tests that we can find a node using the _FindNode() functoin"""
  103. node = self.dtb.GetRoot()._FindNode('i2c@0')
  104. self.assertEqual('i2c@0', node.name)
  105. subnode = node._FindNode('pmic@9')
  106. self.assertEqual('pmic@9', subnode.name)
  107. class TestProp(unittest.TestCase):
  108. """Test operation of the Prop class"""
  109. @classmethod
  110. def setUpClass(cls):
  111. tools.PrepareOutputDir(None)
  112. @classmethod
  113. def tearDownClass(cls):
  114. tools._FinaliseForTest()
  115. def setUp(self):
  116. self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
  117. self.node = self.dtb.GetNode('/spl-test')
  118. self.fdt = self.dtb.GetFdtObj()
  119. def testGetEmpty(self):
  120. """Tests the GetEmpty() function for the various supported types"""
  121. self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
  122. self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
  123. self.assertEqual(chr(0) * 4, fdt.Prop.GetEmpty(fdt.TYPE_INT))
  124. self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
  125. def testGetOffset(self):
  126. """Test we can get the offset of a property"""
  127. prop = self.node.props['longbytearray']
  128. # Add 12, which is sizeof(struct fdt_property), to get to start of data
  129. offset = prop.GetOffset() + 12
  130. data = self.dtb._fdt[offset:offset + len(prop.value)]
  131. bytes = [chr(x) for x in data]
  132. self.assertEqual(bytes, prop.value)
  133. def testWiden(self):
  134. """Test widening of values"""
  135. node2 = self.dtb.GetNode('/spl-test2')
  136. prop = self.node.props['intval']
  137. # No action
  138. prop2 = node2.props['intval']
  139. prop.Widen(prop2)
  140. self.assertEqual(fdt.TYPE_INT, prop.type)
  141. self.assertEqual(1, fdt32_to_cpu(prop.value))
  142. # Convert singla value to array
  143. prop2 = self.node.props['intarray']
  144. prop.Widen(prop2)
  145. self.assertEqual(fdt.TYPE_INT, prop.type)
  146. self.assertTrue(isinstance(prop.value, list))
  147. # A 4-byte array looks like a single integer. When widened by a longer
  148. # byte array, it should turn into an array.
  149. prop = self.node.props['longbytearray']
  150. prop2 = node2.props['longbytearray']
  151. self.assertFalse(isinstance(prop2.value, list))
  152. self.assertEqual(4, len(prop2.value))
  153. prop2.Widen(prop)
  154. self.assertTrue(isinstance(prop2.value, list))
  155. self.assertEqual(9, len(prop2.value))
  156. # Similarly for a string array
  157. prop = self.node.props['stringval']
  158. prop2 = node2.props['stringarray']
  159. self.assertFalse(isinstance(prop.value, list))
  160. self.assertEqual(7, len(prop.value))
  161. prop.Widen(prop2)
  162. self.assertTrue(isinstance(prop.value, list))
  163. self.assertEqual(3, len(prop.value))
  164. # Enlarging an existing array
  165. prop = self.node.props['stringarray']
  166. prop2 = node2.props['stringarray']
  167. self.assertTrue(isinstance(prop.value, list))
  168. self.assertEqual(2, len(prop.value))
  169. prop.Widen(prop2)
  170. self.assertTrue(isinstance(prop.value, list))
  171. self.assertEqual(3, len(prop.value))
  172. def RunTests(args):
  173. """Run all the test we have for the fdt model
  174. Args:
  175. args: List of positional args provided to fdt. This can hold a test
  176. name to execute (as in 'fdt -t testFdt', for example)
  177. """
  178. result = unittest.TestResult()
  179. sys.argv = [sys.argv[0]]
  180. test_name = args and args[0] or None
  181. for module in (TestFdt, TestNode, TestProp):
  182. if test_name:
  183. try:
  184. suite = unittest.TestLoader().loadTestsFromName(test_name, module)
  185. except AttributeError:
  186. continue
  187. else:
  188. suite = unittest.TestLoader().loadTestsFromTestCase(module)
  189. suite.run(result)
  190. print result
  191. for _, err in result.errors:
  192. print err
  193. for _, err in result.failures:
  194. print err
  195. if __name__ != '__main__':
  196. sys.exit(1)
  197. parser = OptionParser()
  198. parser.add_option('-t', '--test', action='store_true', dest='test',
  199. default=False, help='run tests')
  200. (options, args) = parser.parse_args()
  201. # Run our meagre tests
  202. if options.test:
  203. RunTests(args)