1# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) 2# pylibfdt - Tests for Flat Device Tree manipulation in Python 3# Copyright (C) 2017 Google, Inc. 4# Written by Simon Glass <sjg@chromium.org> 5# 6 7import struct 8import sys 9import types 10import unittest 11 12sys.path.insert(0, '../pylibfdt') 13import libfdt 14from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL 15 16TEST_ADDR_1H = 0xdeadbeef 17TEST_ADDR_1L = 0x00000000 18TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L 19TEST_ADDR_1 = 0x8000000000000000 20TEST_SIZE_1H = 0x00000000 21TEST_SIZE_1L = 0x00100000 22TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L 23TEST_ADDR_2H = 0 24TEST_ADDR_2L = 123456789 25TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L 26TEST_SIZE_2H = 0 27TEST_SIZE_2L = 0o10000 28TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L 29 30TEST_VALUE_1 = 0xdeadbeef 31TEST_VALUE_2 = 123456789 32 33TEST_VALUE64_1H = 0xdeadbeef 34TEST_VALUE64_1L = 0x01abcdef 35TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L 36 37PHANDLE_1 = 0x2000 38PHANDLE_2 = 0x2001 39 40TEST_BYTES_1 = b'hello world' 41 42TEST_STRING_1 = 'hello world' 43TEST_STRING_2 = 'hi world' 44TEST_STRING_3 = u'unicode \u01d3' 45 46 47def get_err(err_code): 48 """Convert an error code into an error message 49 50 Args: 51 err_code: Error code value (FDT_ERR_...) 52 53 Returns: 54 String error code 55 """ 56 return 'pylibfdt error %d: %s' % (-err_code, libfdt.strerror(-err_code)) 57 58def _ReadFdt(fname): 59 """Read a device tree file into an Fdt object, ready for use 60 61 Args: 62 fname: Filename to read from 63 64 Returns: 65 Fdt bytearray suitable for passing to libfdt functions 66 """ 67 with open(fname, mode='rb') as f: 68 return libfdt.Fdt(f.read()) 69 70class PyLibfdtBasicTests(unittest.TestCase): 71 """Test class for basic pylibfdt access functions 72 73 Properties: 74 fdt: Device tree file used for testing 75 """ 76 77 def setUp(self): 78 """Read in the device tree we use for testing""" 79 self.fdt = _ReadFdt('test_tree1.dtb') 80 self.fdt2 = _ReadFdt('test_props.dtb') 81 self.fdt3 = _ReadFdt('aliases.dtb') 82 83 def GetPropList(self, node_path): 84 """Read a list of properties from a node 85 86 Args: 87 node_path: Full path to node, e.g. '/subnode@1/subsubnode' 88 89 Returns: 90 List of property names for that node, e.g. ['compatible', 'reg'] 91 """ 92 prop_list = [] 93 node = self.fdt.path_offset(node_path) 94 poffset = self.fdt.first_property_offset(node, QUIET_NOTFOUND) 95 while poffset > 0: 96 prop = self.fdt.get_property_by_offset(poffset) 97 prop_list.append(prop.name) 98 poffset = self.fdt.next_property_offset(poffset, QUIET_NOTFOUND) 99 return prop_list 100 101 def GetSubnodes(self, node_path): 102 """Read a list of subnodes from a node 103 104 Args: 105 node_path: Full path to node, e.g. '/subnode@1/subsubnode' 106 107 Returns: 108 List of subnode names for that node, e.g. ['subsubnode', 'ss1'] 109 """ 110 subnode_list = [] 111 node = self.fdt.path_offset(node_path) 112 offset = self.fdt.first_subnode(node, QUIET_NOTFOUND) 113 while offset > 0: 114 name = self.fdt.get_name(offset) 115 subnode_list.append(name) 116 offset = self.fdt.next_subnode(offset, QUIET_NOTFOUND) 117 return subnode_list 118 119 def testImport(self): 120 """Check that we can import the library correctly""" 121 self.assertEqual(type(libfdt), types.ModuleType) 122 123 def testBadFdt(self): 124 """Check that a filename provided accidentally is not accepted""" 125 with self.assertRaises(FdtException) as e: 126 fdt = libfdt.Fdt(b'a string') 127 self.assertEqual(e.exception.err, -libfdt.BADMAGIC) 128 129 def testSubnodeOffset(self): 130 """check that we can locate a subnode by name""" 131 node1 = self.fdt.path_offset('/subnode@1') 132 self.assertEqual(self.fdt.subnode_offset(0, 'subnode@1'), node1) 133 134 with self.assertRaises(FdtException) as e: 135 self.fdt.subnode_offset(0, 'missing') 136 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 137 138 node2 = self.fdt.path_offset('/subnode@1/subsubnode') 139 self.assertEqual(self.fdt.subnode_offset(node1, 'subsubnode'), node2) 140 141 def testPathOffset(self): 142 """Check that we can find the offset of a node""" 143 self.assertEqual(self.fdt.path_offset('/'), 0) 144 self.assertTrue(self.fdt.path_offset('/subnode@1') > 0) 145 with self.assertRaises(FdtException) as e: 146 self.fdt.path_offset('/wibble') 147 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 148 self.assertEqual(self.fdt.path_offset('/wibble', QUIET_NOTFOUND), 149 -libfdt.NOTFOUND) 150 151 def testPropertyOffset(self): 152 """Walk through all the properties in the root node""" 153 offset = self.fdt.first_property_offset(0) 154 self.assertTrue(offset > 0) 155 for i in range(5): 156 next_offset = self.fdt.next_property_offset(offset) 157 self.assertTrue(next_offset > offset) 158 offset = next_offset 159 self.assertEqual(self.fdt.next_property_offset(offset, QUIET_NOTFOUND), 160 -libfdt.NOTFOUND) 161 162 def testPropertyOffsetExceptions(self): 163 """Check that exceptions are raised as expected""" 164 with self.assertRaises(FdtException) as e: 165 self.fdt.first_property_offset(107) 166 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 167 168 # Quieten the NOTFOUND exception and check that a BADOFFSET 169 # exception is still raised. 170 with self.assertRaises(FdtException) as e: 171 self.fdt.first_property_offset(107, QUIET_NOTFOUND) 172 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 173 with self.assertRaises(FdtException) as e: 174 self.fdt.next_property_offset(107, QUIET_NOTFOUND) 175 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 176 177 # Check that NOTFOUND can be quietened. 178 node = self.fdt.path_offset('/subnode@1/ss1') 179 self.assertEqual(self.fdt.first_property_offset(node, QUIET_NOTFOUND), 180 -libfdt.NOTFOUND) 181 with self.assertRaises(FdtException) as e: 182 self.fdt.first_property_offset(node) 183 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 184 185 def testGetName(self): 186 """Check that we can get the name of a node""" 187 self.assertEqual(self.fdt.get_name(0), '') 188 node = self.fdt.path_offset('/subnode@1/subsubnode') 189 self.assertEqual(self.fdt.get_name(node), 'subsubnode') 190 191 with self.assertRaises(FdtException) as e: 192 self.fdt.get_name(-2) 193 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 194 195 def testGetPropertyByOffset(self): 196 """Check that we can read the name and contents of a property""" 197 root = 0 198 poffset = self.fdt.first_property_offset(root) 199 prop = self.fdt.get_property_by_offset(poffset) 200 self.assertEqual(prop.name, 'compatible') 201 self.assertEqual(prop, b'test_tree1\0') 202 203 with self.assertRaises(FdtException) as e: 204 self.fdt.get_property_by_offset(-2) 205 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 206 self.assertEqual( 207 -libfdt.BADOFFSET, 208 self.fdt.get_property_by_offset(-2, [libfdt.BADOFFSET])) 209 210 def testGetProp(self): 211 """Check that we can read the contents of a property by name""" 212 root = self.fdt.path_offset('/') 213 value = self.fdt.getprop(root, "compatible") 214 self.assertEqual(value, b'test_tree1\0') 215 self.assertEqual(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing', 216 QUIET_NOTFOUND)) 217 218 with self.assertRaises(FdtException) as e: 219 self.fdt.getprop(root, 'missing') 220 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 221 222 node = self.fdt.path_offset('/subnode@1/subsubnode') 223 value = self.fdt.getprop(node, "compatible") 224 self.assertEqual(value, b'subsubnode1\0subsubnode\0') 225 226 def testStrError(self): 227 """Check that we can get an error string""" 228 self.assertEqual(libfdt.strerror(-libfdt.NOTFOUND), 229 'FDT_ERR_NOTFOUND') 230 231 def testNextNodeOffset(self): 232 """Check that we can walk through nodes""" 233 node_list = [] 234 node = 0 235 depth = 0 236 while depth >= 0: 237 node_list.append([depth, self.fdt.get_name(node)]) 238 node, depth = self.fdt.next_node(node, depth, (libfdt.BADOFFSET,)) 239 self.assertEqual(node_list, [ 240 [0, ''], 241 [1, 'subnode@1'], 242 [2, 'subsubnode'], 243 [2, 'ss1'], 244 [1, 'subnode@2'], 245 [2, 'subsubnode@0'], 246 [2, 'ss2'], 247 ]) 248 249 def testFirstNextSubnodeOffset(self): 250 """Check that we can walk through subnodes""" 251 node_list = [] 252 node = self.fdt.first_subnode(0, QUIET_NOTFOUND) 253 while node >= 0: 254 node_list.append(self.fdt.get_name(node)) 255 node = self.fdt.next_subnode(node, QUIET_NOTFOUND) 256 self.assertEqual(node_list, ['subnode@1', 'subnode@2']) 257 258 def testFirstNextSubnodeOffsetExceptions(self): 259 """Check except handling for first/next subnode functions""" 260 node = self.fdt.path_offset('/subnode@1/subsubnode', QUIET_NOTFOUND) 261 self.assertEqual(self.fdt.first_subnode(node, QUIET_NOTFOUND), 262 -libfdt.NOTFOUND) 263 with self.assertRaises(FdtException) as e: 264 self.fdt.first_subnode(node) 265 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 266 267 node = self.fdt.path_offset('/subnode@1/ss1', QUIET_NOTFOUND) 268 self.assertEqual(self.fdt.next_subnode(node, QUIET_NOTFOUND), 269 -libfdt.NOTFOUND) 270 with self.assertRaises(FdtException) as e: 271 self.fdt.next_subnode(node) 272 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 273 274 def testDeleteProperty(self): 275 """Test that we can delete a property""" 276 node_name = '/subnode@1' 277 self.assertEqual(self.GetPropList(node_name), 278 ['compatible', 'reg', 'prop-int']) 279 node = self.fdt.path_offset('/%s' % node_name) 280 self.assertEqual(self.fdt.delprop(node, 'reg'), 0) 281 self.assertEqual(self.GetPropList(node_name), 282 ['compatible', 'prop-int']) 283 284 def testHeader(self): 285 """Test that we can access the header values""" 286 self.assertEqual(self.fdt.magic(), 0xd00dfeed) 287 self.assertEqual(self.fdt.totalsize(), len(self.fdt._fdt)) 288 self.assertEqual(self.fdt.off_dt_struct(), 88) 289 self.assertEqual(self.fdt.off_dt_strings(), 652) 290 self.assertEqual(self.fdt.off_mem_rsvmap(), 40) 291 self.assertEqual(self.fdt.version(), 17) 292 self.assertEqual(self.fdt.last_comp_version(), 16) 293 self.assertEqual(self.fdt.boot_cpuid_phys(), 0) 294 self.assertEqual(self.fdt.size_dt_strings(), 105) 295 self.assertEqual(self.fdt.size_dt_struct(), 564) 296 297 def testPack(self): 298 """Test that we can pack the tree after deleting something""" 299 orig_size = self.fdt.totalsize() 300 node = self.fdt.path_offset('/subnode@2', QUIET_NOTFOUND) 301 self.assertEqual(self.fdt.delprop(node, 'prop-int'), 0) 302 self.assertEqual(orig_size, self.fdt.totalsize()) 303 self.assertEqual(self.fdt.pack(), 0) 304 self.assertTrue(self.fdt.totalsize() < orig_size) 305 self.assertEqual(self.fdt.totalsize(), len(self.fdt.as_bytearray())) 306 307 def testBadPropertyOffset(self): 308 """Test that bad property offsets are detected""" 309 with self.assertRaises(FdtException) as e: 310 self.fdt.get_property_by_offset(13) 311 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 312 with self.assertRaises(FdtException) as e: 313 self.fdt.first_property_offset(3) 314 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 315 with self.assertRaises(FdtException) as e: 316 self.fdt.next_property_offset(3) 317 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 318 319 def testBadPathOffset(self): 320 """Test that bad path names are detected""" 321 with self.assertRaisesRegex(FdtException, get_err(libfdt.BADPATH)): 322 self.fdt.path_offset('not-present') 323 324 def testQuietAll(self): 325 """Check that exceptions can be masked by QUIET_ALL""" 326 self.assertEqual(-libfdt.NOTFOUND, 327 self.fdt.path_offset('/missing', QUIET_ALL)) 328 self.assertEqual(-libfdt.BADOFFSET, 329 self.fdt.get_property_by_offset(13, QUIET_ALL)) 330 self.assertEqual(-libfdt.BADPATH, 331 self.fdt.path_offset('missing', QUIET_ALL)) 332 333 def testIntegers(self): 334 """Check that integers can be passed and returned""" 335 self.assertEqual(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0)) 336 node2 = self.fdt.path_offset('/subnode@2') 337 self.assertEqual(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2)) 338 339 def testGetPhandle(self): 340 """Test for the get_phandle() method""" 341 self.assertEqual(0, self.fdt.get_phandle(0)) 342 node2 = self.fdt.path_offset('/subnode@2') 343 self.assertEqual(0x2000, self.fdt.get_phandle(node2)) 344 345 def testGetAlias(self): 346 """Test for the get_alias() method""" 347 self.assertEqual("/subnode@1", self.fdt3.get_alias('s1')) 348 self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1')) 349 self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1')) 350 351 def testParentOffset(self): 352 """Test for the parent_offset() method""" 353 self.assertEqual(-libfdt.NOTFOUND, 354 self.fdt.parent_offset(0, QUIET_NOTFOUND)) 355 with self.assertRaises(FdtException) as e: 356 self.fdt.parent_offset(0) 357 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 358 359 node1 = self.fdt.path_offset('/subnode@2') 360 self.assertEqual(0, self.fdt.parent_offset(node1)) 361 node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') 362 self.assertEqual(node1, self.fdt.parent_offset(node2)) 363 364 def testNodeOffsetByPhandle(self): 365 """Test for the node_offset_by_phandle() method""" 366 self.assertEqual(-libfdt.NOTFOUND, 367 self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND)) 368 node1 = self.fdt.path_offset('/subnode@2') 369 self.assertEqual(node1, self.fdt.node_offset_by_phandle(0x2000)) 370 node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') 371 self.assertEqual(node2, self.fdt.node_offset_by_phandle(0x2001)) 372 373 def get_prop(self, name): 374 return self.fdt2.getprop(0, name) 375 376 def testGetIntProperties(self): 377 """Test that we can access properties as integers""" 378 self.assertEqual(0xdeadbeef, self.get_prop("prop-hex32").as_uint32()) 379 self.assertEqual(123, self.get_prop("prop-uint32").as_uint32()) 380 self.assertEqual(-2, self.get_prop("prop-int32").as_int32()) 381 self.assertEqual(9223372036854775807, 382 self.get_prop("prop-uint64").as_uint64()) 383 self.assertEqual(-2, self.get_prop("prop-int64").as_int64()) 384 385 def testReserveMap(self): 386 """Test that we can access the memory reserve map""" 387 self.assertEqual(2, self.fdt.num_mem_rsv()) 388 self.assertEqual([ 0xdeadbeef00000000, 0x100000], 389 self.fdt.get_mem_rsv(0)) 390 self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1)) 391 392 def testEmpty(self): 393 """Test that we can create an empty tree""" 394 self.assertEqual(-libfdt.NOSPACE, 395 Fdt.create_empty_tree(1, (libfdt.NOSPACE,))) 396 fdt = Fdt.create_empty_tree(128) 397 self.assertEqual(128, fdt.totalsize()) 398 399 def testOpenInto(self): 400 """Test that we can resize a tree""" 401 fdt = Fdt.create_empty_tree(128) 402 self.assertEqual(128, fdt.totalsize()) 403 fdt.resize(256) 404 self.assertEqual(256, fdt.totalsize()) 405 fdt.pack() 406 self.assertTrue(fdt.totalsize() < 128) 407 408 def testSetProp(self): 409 """Test that we can update and create properties""" 410 node = self.fdt.path_offset('/subnode@1') 411 self.fdt.setprop(node, 'compatible', TEST_BYTES_1) 412 self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'compatible')) 413 414 # Check that this property is missing, and that we don't have space to 415 # add it 416 self.assertEqual(-libfdt.NOTFOUND, 417 self.fdt.getprop(node, 'missing', QUIET_NOTFOUND)) 418 self.assertEqual(-libfdt.NOSPACE, 419 self.fdt.setprop(node, 'missing', TEST_BYTES_1, 420 quiet=(libfdt.NOSPACE,))) 421 422 # Expand the device tree so we now have room 423 self.fdt.resize(self.fdt.totalsize() + 50) 424 self.fdt.setprop(node, 'missing', TEST_BYTES_1) 425 self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'missing')) 426 427 def testSetPropU32(self): 428 """Test that we can update and create integer properties""" 429 node = 0 430 prop = 'prop-int' 431 self.fdt.setprop_u32(node, prop, TEST_VALUE_1) 432 self.assertEqual(struct.pack('>I', TEST_VALUE_1), 433 self.fdt.getprop(node, prop)) 434 435 def testSetPropU64(self): 436 """Test that we can update and create integer properties""" 437 node = 0 438 prop = 'prop-int64' 439 self.fdt.setprop_u64(node, prop, TEST_VALUE64_1) 440 self.assertEqual(struct.pack('>Q', TEST_VALUE64_1), 441 self.fdt.getprop(node, prop)) 442 443 def testSetPropStr(self): 444 """Test that we can set a property to a particular string""" 445 node = 0 446 prop = 'prop-str' 447 self.assertEqual(TEST_STRING_1, self.fdt.getprop(node, prop).as_str()) 448 self.fdt.setprop_str(node, prop, TEST_STRING_2) 449 self.assertEqual(TEST_STRING_2, self.fdt.getprop(node, prop).as_str()) 450 with self.assertRaises(ValueError) as e: 451 self.fdt.getprop(node, 'prop-int').as_str() 452 self.assertIn('lacks nul termination', str(e.exception)) 453 454 node2 = self.fdt.path_offset('/subnode@1/subsubnode') 455 with self.assertRaises(ValueError) as e: 456 self.fdt.getprop(node2, 'compatible').as_str() 457 self.assertIn('embedded nul', str(e.exception)) 458 459 # Expand the device tree so we now have room 460 self.fdt.resize(self.fdt.totalsize() + 50) 461 prop = 'prop-unicode' 462 self.fdt.setprop_str(node, prop, TEST_STRING_3) 463 self.assertEqual(TEST_STRING_3, 464 self.fdt.getprop(node, prop).as_str()) 465 466 def testSetName(self): 467 """Test that we can update a node name""" 468 node = self.fdt.path_offset('/subnode@1') 469 old_val = self.fdt.get_name(node) 470 self.fdt.set_name(node, 'test') 471 self.assertEqual('test', self.fdt.get_name(node)) 472 473 with self.assertRaises(ValueError) as e: 474 self.fdt.set_name(node, 'some\0name') 475 self.assertIn('embedded nul', str(e.exception)) 476 477 with self.assertRaises(ValueError) as e: 478 self.fdt.set_name(node, 'name\0') 479 self.assertIn('embedded nul', str(e.exception)) 480 481 def testAddDeleteNodes(self): 482 """Test that we can add and delete nodes""" 483 node_name = '/subnode@1' 484 self.assertEqual(self.GetSubnodes(node_name), ['subsubnode', 'ss1']) 485 node = self.fdt.path_offset('%s/subsubnode' % node_name) 486 self.assertEqual(self.fdt.del_node(node, 'subsubnode'), 0) 487 self.assertEqual(self.GetSubnodes(node_name), ['ss1']) 488 489 node = self.fdt.path_offset(node_name) 490 offset = self.fdt.add_subnode(node, 'more') 491 self.assertTrue(offset > 0) 492 self.assertEqual(self.GetSubnodes(node_name), ['more', 'ss1']) 493 494 495class PyLibfdtSwTests(unittest.TestCase): 496 """Test class for pylibfdt sequential-write DT creation 497 """ 498 def assertOk(self, err_code): 499 self.assertEqual(0, err_code) 500 501 def testCreate(self): 502 # First check the minimum size and also the FdtSw() constructor 503 with self.assertRaisesRegex(FdtException, get_err(libfdt.NOSPACE)): 504 self.assertEqual(-libfdt.NOSPACE, FdtSw(3)) 505 506 sw = FdtSw() 507 sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1) 508 sw.add_reservemap_entry(TEST_ADDR_2, TEST_SIZE_2) 509 sw.finish_reservemap() 510 511 sw.begin_node('') 512 sw.property_string('compatible', 'test_tree1') 513 sw.property_u32('prop-int', TEST_VALUE_1) 514 515 sw.property_u32('prop-int', TEST_VALUE_1) 516 sw.property_u64('prop-int64', TEST_VALUE64_1) 517 sw.property_string('prop-str', TEST_STRING_1) 518 sw.property_u32('#address-cells', 1) 519 sw.property_u32('#size-cells', 0) 520 521 sw.begin_node('subnode@1') 522 sw.property_string('compatible', 'subnode1') 523 sw.property_u32('reg', 1) 524 sw.property_cell('prop-int', TEST_VALUE_1) 525 sw.property('data', b'\x00data\x01') 526 sw.begin_node('subsubnode') 527 sw.property('compatible', b'subsubnode1\0subsubnode') 528 sw.property_cell('prop-int', TEST_VALUE_1) 529 sw.end_node() 530 sw.begin_node('ss1') 531 sw.end_node() 532 sw.end_node() 533 534 for i in range(2, 11): 535 with sw.add_node('subnode@%d' % i): 536 sw.property_u32('reg', 2) 537 sw.property_cell('linux,phandle', PHANDLE_1) 538 sw.property_cell('prop-int', TEST_VALUE_2) 539 sw.property_u32('#address-cells', 1) 540 sw.property_u32('#size-cells', 0) 541 with sw.add_node('subsubnode@0'): 542 sw.property_u32('reg', 0) 543 sw.property_cell('phandle', PHANDLE_2) 544 sw.property('compatible', b'subsubnode2\0subsubnode') 545 sw.property_cell('prop-int', TEST_VALUE_2) 546 with sw.add_node('ss2'): 547 pass 548 sw.end_node() 549 550 fdt = sw.as_fdt() 551 self.assertEqual(2, fdt.num_mem_rsv()) 552 self.assertEqual([TEST_ADDR_1, TEST_SIZE_1], fdt.get_mem_rsv(0)) 553 554 # Make sure we can add a few more things 555 with sw.add_node('another'): 556 sw.property_u32('reg', 3) 557 558 # Make sure we can read from the tree too 559 node = sw.path_offset('/subnode@1') 560 self.assertEqual(b'subnode1\0', sw.getprop(node, 'compatible')) 561 562 # Make sure we did at least two resizes 563 self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2) 564 565 566class PyLibfdtRoTests(unittest.TestCase): 567 """Test class for read-only pylibfdt access functions 568 569 This just tests a few simple cases. Most of the tests are in 570 PyLibfdtBasicTests. 571 572 Properties: 573 fdt: Device tree file used for testing 574 """ 575 576 def setUp(self): 577 """Read in the device tree we use for testing""" 578 with open('test_tree1.dtb', mode='rb') as f: 579 self.fdt = libfdt.FdtRo(f.read()) 580 581 def testAccess(self): 582 """Basic sanity check for the FdtRo class""" 583 node = self.fdt.path_offset('/subnode@1') 584 self.assertEqual(b'subnode1\0', 585 self.fdt.getprop(node, 'compatible')) 586 node = self.fdt.first_subnode(node) 587 self.assertEqual(b'this is a placeholder string\0string2\0', 588 self.fdt.getprop(node, 'placeholder')) 589 590 591if __name__ == "__main__": 592 unittest.main() 593