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