xref: /netbsd-src/external/gpl2/dtc/dist/tests/pylibfdt_tests.py (revision cc7d2833ecf67da5a5ddc470841931eb9f6723e4)
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