test_fdt.py 26 KB

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