Home | History | Annotate | Line # | Download | only in tests
      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 (at] chromium.org>
      5 #
      6 
      7 import struct
      8 import sys
      9 import types
     10 import unittest
     11 
     12 sys.path.insert(0, '../pylibfdt')
     13 import libfdt
     14 from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL
     15 
     16 TEST_ADDR_1H = 0xdeadbeef
     17 TEST_ADDR_1L = 0x00000000
     18 TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L
     19 TEST_ADDR_1 = 0x8000000000000000
     20 TEST_SIZE_1H = 0x00000000
     21 TEST_SIZE_1L = 0x00100000
     22 TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L
     23 TEST_ADDR_2H = 0
     24 TEST_ADDR_2L = 123456789
     25 TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L
     26 TEST_SIZE_2H = 0
     27 TEST_SIZE_2L = 0o10000
     28 TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L
     29 
     30 TEST_VALUE_1 = 0xdeadbeef
     31 TEST_VALUE_2 = 123456789
     32 
     33 TEST_VALUE64_1H = 0xdeadbeef
     34 TEST_VALUE64_1L = 0x01abcdef
     35 TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L
     36 
     37 PHANDLE_1 = 0x2000
     38 PHANDLE_2 = 0x2001
     39 
     40 TEST_BYTES_1 = b'hello world'
     41 
     42 TEST_STRING_1 = 'hello world'
     43 TEST_STRING_2 = 'hi world'
     44 TEST_STRING_3 = u'unicode \u01d3'
     45 
     46 
     47 def 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 
     58 def _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 
     69 class 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 
    494 class 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 
    564 class 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 
    588 if __name__ == "__main__":
    589     unittest.main()
    590