mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-21 18:53:06 +00:00
d8318feba1
The python tools' test utilities handle printing test results, but the output is quite bare compared to an ordinary unittest run. Delegate printing the results to a unittest text runner, which gives us niceties like clear separation between each test's result and how long it took to run the test suite. Unfortunately it does not print info for skipped tests by default, but this can be handled later by a custom test result subclass. It also does not print the tool name; manually print a heading that includes the toolname so that the outputs of each tool's tests are distinguishable in the CI output. Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
814 lines
30 KiB
Python
Executable file
814 lines
30 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-2.0+
|
|
# Copyright (c) 2018 Google, Inc
|
|
# Written by Simon Glass <sjg@chromium.org>
|
|
#
|
|
|
|
from optparse import OptionParser
|
|
import glob
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
# Bring in the patman libraries
|
|
our_path = os.path.dirname(os.path.realpath(__file__))
|
|
sys.path.insert(1, os.path.join(our_path, '..'))
|
|
|
|
# Bring in the libfdt module
|
|
sys.path.insert(2, 'scripts/dtc/pylibfdt')
|
|
sys.path.insert(2, os.path.join(our_path, '../../scripts/dtc/pylibfdt'))
|
|
sys.path.insert(2, os.path.join(our_path,
|
|
'../../build-sandbox_spl/scripts/dtc/pylibfdt'))
|
|
|
|
from dtoc import fdt
|
|
from dtoc import fdt_util
|
|
from dtoc.fdt_util import fdt32_to_cpu, fdt64_to_cpu
|
|
from dtoc.fdt import Type, BytesToValue
|
|
import libfdt
|
|
from patman import command
|
|
from patman import test_util
|
|
from patman import tools
|
|
|
|
def _GetPropertyValue(dtb, node, prop_name):
|
|
"""Low-level function to get the property value based on its offset
|
|
|
|
This looks directly in the device tree at the property's offset to find
|
|
its value. It is useful as a check that the property is in the correct
|
|
place.
|
|
|
|
Args:
|
|
node: Node to look in
|
|
prop_name: Property name to find
|
|
|
|
Returns:
|
|
Tuple:
|
|
Prop object found
|
|
Value of property as a string (found using property offset)
|
|
"""
|
|
prop = node.props[prop_name]
|
|
|
|
# Add 12, which is sizeof(struct fdt_property), to get to start of data
|
|
offset = prop.GetOffset() + 12
|
|
data = dtb.GetContents()[offset:offset + len(prop.value)]
|
|
return prop, [chr(x) for x in data]
|
|
|
|
def find_dtb_file(dts_fname):
|
|
"""Locate a test file in the test/ directory
|
|
|
|
Args:
|
|
dts_fname (str): Filename to find, e.g. 'dtoc_test_simple.dts]
|
|
|
|
Returns:
|
|
str: Path to the test filename
|
|
"""
|
|
return os.path.join('tools/dtoc/test', dts_fname)
|
|
|
|
|
|
class TestFdt(unittest.TestCase):
|
|
"""Tests for the Fdt module
|
|
|
|
This includes unit tests for some functions and functional tests for the fdt
|
|
module.
|
|
"""
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
tools.prepare_output_dir(None)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
tools.finalise_output_dir()
|
|
|
|
def setUp(self):
|
|
self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
|
|
|
|
def testFdt(self):
|
|
"""Test that we can open an Fdt"""
|
|
self.dtb.Scan()
|
|
root = self.dtb.GetRoot()
|
|
self.assertTrue(isinstance(root, fdt.Node))
|
|
|
|
def testGetNode(self):
|
|
"""Test the GetNode() method"""
|
|
node = self.dtb.GetNode('/spl-test')
|
|
self.assertTrue(isinstance(node, fdt.Node))
|
|
|
|
node = self.dtb.GetNode('/i2c@0/pmic@9')
|
|
self.assertTrue(isinstance(node, fdt.Node))
|
|
self.assertEqual('pmic@9', node.name)
|
|
self.assertIsNone(self.dtb.GetNode('/i2c@0/pmic@9/missing'))
|
|
|
|
node = self.dtb.GetNode('/')
|
|
self.assertTrue(isinstance(node, fdt.Node))
|
|
self.assertEqual(0, node.Offset())
|
|
|
|
def testFlush(self):
|
|
"""Check that we can flush the device tree out to its file"""
|
|
fname = self.dtb._fname
|
|
with open(fname, 'rb') as fd:
|
|
data = fd.read()
|
|
os.remove(fname)
|
|
with self.assertRaises(IOError):
|
|
open(fname, 'rb')
|
|
self.dtb.Flush()
|
|
with open(fname, 'rb') as fd:
|
|
data = fd.read()
|
|
|
|
def testPack(self):
|
|
"""Test that packing a device tree works"""
|
|
self.dtb.Pack()
|
|
|
|
def testGetFdtRaw(self):
|
|
"""Tetst that we can access the raw device-tree data"""
|
|
self.assertTrue(isinstance(self.dtb.GetContents(), bytes))
|
|
|
|
def testGetProps(self):
|
|
"""Tests obtaining a list of properties"""
|
|
node = self.dtb.GetNode('/spl-test')
|
|
props = self.dtb.GetProps(node)
|
|
self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible',
|
|
'int64val', 'intarray', 'intval', 'longbytearray',
|
|
'maybe-empty-int', 'notstring', 'stringarray',
|
|
'stringval', 'u-boot,dm-pre-reloc'],
|
|
sorted(props.keys()))
|
|
|
|
def testCheckError(self):
|
|
"""Tests the ChecKError() function"""
|
|
with self.assertRaises(ValueError) as e:
|
|
fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
|
|
self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
|
|
|
|
def testGetFdt(self):
|
|
node = self.dtb.GetNode('/spl-test')
|
|
self.assertEqual(self.dtb, node.GetFdt())
|
|
|
|
def testBytesToValue(self):
|
|
self.assertEqual(BytesToValue(b'this\0is\0'),
|
|
(Type.STRING, ['this', 'is']))
|
|
|
|
class TestNode(unittest.TestCase):
|
|
"""Test operation of the Node class"""
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
tools.prepare_output_dir(None)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
tools.finalise_output_dir()
|
|
|
|
def setUp(self):
|
|
self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
|
|
self.node = self.dtb.GetNode('/spl-test')
|
|
self.fdt = self.dtb.GetFdtObj()
|
|
|
|
def testOffset(self):
|
|
"""Tests that we can obtain the offset of a node"""
|
|
self.assertTrue(self.node.Offset() > 0)
|
|
|
|
def testDelete(self):
|
|
"""Tests that we can delete a property"""
|
|
node2 = self.dtb.GetNode('/spl-test2')
|
|
offset1 = node2.Offset()
|
|
self.node.DeleteProp('intval')
|
|
offset2 = node2.Offset()
|
|
self.assertTrue(offset2 < offset1)
|
|
self.node.DeleteProp('intarray')
|
|
offset3 = node2.Offset()
|
|
self.assertTrue(offset3 < offset2)
|
|
with self.assertRaises(libfdt.FdtException):
|
|
self.node.DeleteProp('missing')
|
|
|
|
def testDeleteGetOffset(self):
|
|
"""Test that property offset update when properties are deleted"""
|
|
self.node.DeleteProp('intval')
|
|
prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
|
|
self.assertEqual(prop.value, value)
|
|
|
|
def testFindNode(self):
|
|
"""Tests that we can find a node using the FindNode() functoin"""
|
|
node = self.dtb.GetRoot().FindNode('i2c@0')
|
|
self.assertEqual('i2c@0', node.name)
|
|
subnode = node.FindNode('pmic@9')
|
|
self.assertEqual('pmic@9', subnode.name)
|
|
self.assertEqual(None, node.FindNode('missing'))
|
|
|
|
def testRefreshMissingNode(self):
|
|
"""Test refreshing offsets when an extra node is present in dtb"""
|
|
# Delete it from our tables, not the device tree
|
|
del self.dtb._root.subnodes[-1]
|
|
with self.assertRaises(ValueError) as e:
|
|
self.dtb.Refresh()
|
|
self.assertIn('Internal error, offset', str(e.exception))
|
|
|
|
def testRefreshExtraNode(self):
|
|
"""Test refreshing offsets when an expected node is missing"""
|
|
# Delete it from the device tre, not our tables
|
|
self.fdt.del_node(self.node.Offset())
|
|
with self.assertRaises(ValueError) as e:
|
|
self.dtb.Refresh()
|
|
self.assertIn('Internal error, node name mismatch '
|
|
'spl-test != spl-test2', str(e.exception))
|
|
|
|
def testRefreshMissingProp(self):
|
|
"""Test refreshing offsets when an extra property is present in dtb"""
|
|
# Delete it from our tables, not the device tree
|
|
del self.node.props['notstring']
|
|
with self.assertRaises(ValueError) as e:
|
|
self.dtb.Refresh()
|
|
self.assertIn("Internal error, node '/spl-test' property 'notstring' missing, offset ",
|
|
str(e.exception))
|
|
|
|
def testLookupPhandle(self):
|
|
"""Test looking up a single phandle"""
|
|
dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
|
|
node = dtb.GetNode('/phandle-source2')
|
|
prop = node.props['clocks']
|
|
target = dtb.GetNode('/phandle-target')
|
|
self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
|
|
|
|
def testAddNodeSpace(self):
|
|
"""Test adding a single node when out of space"""
|
|
self.fdt.pack()
|
|
self.node.AddSubnode('subnode')
|
|
with self.assertRaises(libfdt.FdtException) as e:
|
|
self.dtb.Sync(auto_resize=False)
|
|
self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
|
|
|
|
self.dtb.Sync(auto_resize=True)
|
|
offset = self.fdt.path_offset('/spl-test/subnode')
|
|
self.assertTrue(offset > 0)
|
|
|
|
def testAddNodes(self):
|
|
"""Test adding various subnode and properies"""
|
|
node = self.dtb.GetNode('/i2c@0')
|
|
|
|
# Add one more node next to the pmic one
|
|
sn1 = node.AddSubnode('node-one')
|
|
sn1.AddInt('integer-a', 12)
|
|
sn1.AddInt('integer-b', 23)
|
|
|
|
# Sync so that everything is clean
|
|
self.dtb.Sync(auto_resize=True)
|
|
|
|
# Add two subnodes next to pmic and node-one
|
|
sn2 = node.AddSubnode('node-two')
|
|
sn2.AddInt('integer-2a', 34)
|
|
sn2.AddInt('integer-2b', 45)
|
|
|
|
sn3 = node.AddSubnode('node-three')
|
|
sn3.AddInt('integer-3', 123)
|
|
|
|
# Add a property to the node after i2c@0 to check that this is not
|
|
# disturbed by adding a subnode to i2c@0
|
|
orig_node = self.dtb.GetNode('/orig-node')
|
|
orig_node.AddInt('integer-4', 456)
|
|
|
|
# Add a property to the pmic node to check that pmic properties are not
|
|
# disturbed
|
|
pmic = self.dtb.GetNode('/i2c@0/pmic@9')
|
|
pmic.AddInt('integer-5', 567)
|
|
|
|
self.dtb.Sync(auto_resize=True)
|
|
|
|
def testAddOneNode(self):
|
|
"""Testing deleting and adding a subnode before syncing"""
|
|
subnode = self.node.AddSubnode('subnode')
|
|
self.node.AddSubnode('subnode2')
|
|
self.dtb.Sync(auto_resize=True)
|
|
|
|
# Delete a node and add a new one
|
|
subnode.Delete()
|
|
self.node.AddSubnode('subnode3')
|
|
self.dtb.Sync()
|
|
|
|
def testRefreshNameMismatch(self):
|
|
"""Test name mismatch when syncing nodes and properties"""
|
|
prop = self.node.AddInt('integer-a', 12)
|
|
|
|
wrong_offset = self.dtb.GetNode('/i2c@0')._offset
|
|
self.node._offset = wrong_offset
|
|
with self.assertRaises(ValueError) as e:
|
|
self.dtb.Sync()
|
|
self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
|
|
str(e.exception))
|
|
|
|
with self.assertRaises(ValueError) as e:
|
|
self.node.Refresh(wrong_offset)
|
|
self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
|
|
str(e.exception))
|
|
|
|
|
|
class TestProp(unittest.TestCase):
|
|
"""Test operation of the Prop class"""
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
tools.prepare_output_dir(None)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
tools.finalise_output_dir()
|
|
|
|
def setUp(self):
|
|
self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
|
|
self.node = self.dtb.GetNode('/spl-test')
|
|
self.fdt = self.dtb.GetFdtObj()
|
|
|
|
def testMissingNode(self):
|
|
self.assertEqual(None, self.dtb.GetNode('missing'))
|
|
|
|
def testPhandle(self):
|
|
dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
|
|
node = dtb.GetNode('/phandle-source2')
|
|
prop = node.props['clocks']
|
|
self.assertTrue(fdt32_to_cpu(prop.value) > 0)
|
|
|
|
def _ConvertProp(self, prop_name):
|
|
"""Helper function to look up a property in self.node and return it
|
|
|
|
Args:
|
|
Property name to find
|
|
|
|
Return fdt.Prop object for this property
|
|
"""
|
|
p = self.fdt.getprop(self.node.Offset(), prop_name)
|
|
return fdt.Prop(self.node, -1, prop_name, p)
|
|
|
|
def testMakeProp(self):
|
|
"""Test we can convert all the the types that are supported"""
|
|
prop = self._ConvertProp('boolval')
|
|
self.assertEqual(Type.BOOL, prop.type)
|
|
self.assertEqual(True, prop.value)
|
|
|
|
prop = self._ConvertProp('intval')
|
|
self.assertEqual(Type.INT, prop.type)
|
|
self.assertEqual(1, fdt32_to_cpu(prop.value))
|
|
|
|
prop = self._ConvertProp('int64val')
|
|
self.assertEqual(Type.INT, prop.type)
|
|
self.assertEqual(0x123456789abcdef0, fdt64_to_cpu(prop.value))
|
|
|
|
prop = self._ConvertProp('intarray')
|
|
self.assertEqual(Type.INT, prop.type)
|
|
val = [fdt32_to_cpu(val) for val in prop.value]
|
|
self.assertEqual([2, 3, 4], val)
|
|
|
|
prop = self._ConvertProp('byteval')
|
|
self.assertEqual(Type.BYTE, prop.type)
|
|
self.assertEqual(5, ord(prop.value))
|
|
|
|
prop = self._ConvertProp('longbytearray')
|
|
self.assertEqual(Type.BYTE, prop.type)
|
|
val = [ord(val) for val in prop.value]
|
|
self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
|
|
|
|
prop = self._ConvertProp('stringval')
|
|
self.assertEqual(Type.STRING, prop.type)
|
|
self.assertEqual('message', prop.value)
|
|
|
|
prop = self._ConvertProp('stringarray')
|
|
self.assertEqual(Type.STRING, prop.type)
|
|
self.assertEqual(['multi-word', 'message'], prop.value)
|
|
|
|
prop = self._ConvertProp('notstring')
|
|
self.assertEqual(Type.BYTE, prop.type)
|
|
val = [ord(val) for val in prop.value]
|
|
self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
|
|
|
|
def testGetEmpty(self):
|
|
"""Tests the GetEmpty() function for the various supported types"""
|
|
self.assertEqual(True, fdt.Prop.GetEmpty(Type.BOOL))
|
|
self.assertEqual(chr(0), fdt.Prop.GetEmpty(Type.BYTE))
|
|
self.assertEqual(tools.get_bytes(0, 4), fdt.Prop.GetEmpty(Type.INT))
|
|
self.assertEqual('', fdt.Prop.GetEmpty(Type.STRING))
|
|
|
|
def testGetOffset(self):
|
|
"""Test we can get the offset of a property"""
|
|
prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
|
|
self.assertEqual(prop.value, value)
|
|
|
|
def testWiden(self):
|
|
"""Test widening of values"""
|
|
node2 = self.dtb.GetNode('/spl-test2')
|
|
node3 = self.dtb.GetNode('/spl-test3')
|
|
prop = self.node.props['intval']
|
|
|
|
# No action
|
|
prop2 = node2.props['intval']
|
|
prop.Widen(prop2)
|
|
self.assertEqual(Type.INT, prop.type)
|
|
self.assertEqual(1, fdt32_to_cpu(prop.value))
|
|
|
|
# Convert single value to array
|
|
prop2 = self.node.props['intarray']
|
|
prop.Widen(prop2)
|
|
self.assertEqual(Type.INT, prop.type)
|
|
self.assertTrue(isinstance(prop.value, list))
|
|
|
|
# A 4-byte array looks like a single integer. When widened by a longer
|
|
# byte array, it should turn into an array.
|
|
prop = self.node.props['longbytearray']
|
|
prop2 = node2.props['longbytearray']
|
|
prop3 = node3.props['longbytearray']
|
|
self.assertFalse(isinstance(prop2.value, list))
|
|
self.assertEqual(4, len(prop2.value))
|
|
self.assertEqual(b'\x09\x0a\x0b\x0c', prop2.value)
|
|
prop2.Widen(prop)
|
|
self.assertTrue(isinstance(prop2.value, list))
|
|
self.assertEqual(9, len(prop2.value))
|
|
self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\0',
|
|
'\0', '\0', '\0', '\0'], prop2.value)
|
|
prop3.Widen(prop)
|
|
self.assertTrue(isinstance(prop3.value, list))
|
|
self.assertEqual(9, len(prop3.value))
|
|
self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\x0d',
|
|
'\x0e', '\x0f', '\x10', '\0'], prop3.value)
|
|
|
|
# Similarly for a string array
|
|
prop = self.node.props['stringval']
|
|
prop2 = node2.props['stringarray']
|
|
self.assertFalse(isinstance(prop.value, list))
|
|
self.assertEqual(7, len(prop.value))
|
|
prop.Widen(prop2)
|
|
self.assertTrue(isinstance(prop.value, list))
|
|
self.assertEqual(3, len(prop.value))
|
|
|
|
# Enlarging an existing array
|
|
prop = self.node.props['stringarray']
|
|
prop2 = node2.props['stringarray']
|
|
self.assertTrue(isinstance(prop.value, list))
|
|
self.assertEqual(2, len(prop.value))
|
|
prop.Widen(prop2)
|
|
self.assertTrue(isinstance(prop.value, list))
|
|
self.assertEqual(3, len(prop.value))
|
|
|
|
# Widen an array of ints with an int (should do nothing)
|
|
prop = self.node.props['intarray']
|
|
prop2 = node2.props['intval']
|
|
self.assertEqual(Type.INT, prop.type)
|
|
self.assertEqual(3, len(prop.value))
|
|
prop.Widen(prop2)
|
|
self.assertEqual(Type.INT, prop.type)
|
|
self.assertEqual(3, len(prop.value))
|
|
|
|
# Widen an empty bool to an int
|
|
prop = self.node.props['maybe-empty-int']
|
|
prop3 = node3.props['maybe-empty-int']
|
|
self.assertEqual(Type.BOOL, prop.type)
|
|
self.assertEqual(True, prop.value)
|
|
self.assertEqual(Type.INT, prop3.type)
|
|
self.assertFalse(isinstance(prop.value, list))
|
|
self.assertEqual(4, len(prop3.value))
|
|
prop.Widen(prop3)
|
|
self.assertEqual(Type.INT, prop.type)
|
|
self.assertTrue(isinstance(prop.value, list))
|
|
self.assertEqual(1, len(prop.value))
|
|
|
|
def testAdd(self):
|
|
"""Test adding properties"""
|
|
self.fdt.pack()
|
|
# This function should automatically expand the device tree
|
|
self.node.AddZeroProp('one')
|
|
self.node.AddZeroProp('two')
|
|
self.node.AddZeroProp('three')
|
|
self.dtb.Sync(auto_resize=True)
|
|
|
|
# Updating existing properties should be OK, since the device-tree size
|
|
# does not change
|
|
self.fdt.pack()
|
|
self.node.SetInt('one', 1)
|
|
self.node.SetInt('two', 2)
|
|
self.node.SetInt('three', 3)
|
|
self.dtb.Sync(auto_resize=False)
|
|
|
|
# This should fail since it would need to increase the device-tree size
|
|
self.node.AddZeroProp('four')
|
|
with self.assertRaises(libfdt.FdtException) as e:
|
|
self.dtb.Sync(auto_resize=False)
|
|
self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
|
|
self.dtb.Sync(auto_resize=True)
|
|
|
|
def testAddMore(self):
|
|
"""Test various other methods for adding and setting properties"""
|
|
self.node.AddZeroProp('one')
|
|
self.dtb.Sync(auto_resize=True)
|
|
data = self.fdt.getprop(self.node.Offset(), 'one')
|
|
self.assertEqual(0, fdt32_to_cpu(data))
|
|
|
|
self.node.SetInt('one', 1)
|
|
self.dtb.Sync(auto_resize=False)
|
|
data = self.fdt.getprop(self.node.Offset(), 'one')
|
|
self.assertEqual(1, fdt32_to_cpu(data))
|
|
|
|
val = 1234
|
|
self.node.AddInt('integer', val)
|
|
self.dtb.Sync(auto_resize=True)
|
|
data = self.fdt.getprop(self.node.Offset(), 'integer')
|
|
self.assertEqual(val, fdt32_to_cpu(data))
|
|
|
|
val = '123' + chr(0) + '456'
|
|
self.node.AddString('string', val)
|
|
self.dtb.Sync(auto_resize=True)
|
|
data = self.fdt.getprop(self.node.Offset(), 'string')
|
|
self.assertEqual(tools.to_bytes(val) + b'\0', data)
|
|
|
|
self.fdt.pack()
|
|
self.node.SetString('string', val + 'x')
|
|
with self.assertRaises(libfdt.FdtException) as e:
|
|
self.dtb.Sync(auto_resize=False)
|
|
self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
|
|
self.node.SetString('string', val[:-1])
|
|
|
|
prop = self.node.props['string']
|
|
prop.SetData(tools.to_bytes(val))
|
|
self.dtb.Sync(auto_resize=False)
|
|
data = self.fdt.getprop(self.node.Offset(), 'string')
|
|
self.assertEqual(tools.to_bytes(val), data)
|
|
|
|
self.node.AddEmptyProp('empty', 5)
|
|
self.dtb.Sync(auto_resize=True)
|
|
prop = self.node.props['empty']
|
|
prop.SetData(tools.to_bytes(val))
|
|
self.dtb.Sync(auto_resize=False)
|
|
data = self.fdt.getprop(self.node.Offset(), 'empty')
|
|
self.assertEqual(tools.to_bytes(val), data)
|
|
|
|
self.node.SetData('empty', b'123')
|
|
self.assertEqual(b'123', prop.bytes)
|
|
|
|
# Trying adding a lot of data at once
|
|
self.node.AddData('data', tools.get_bytes(65, 20000))
|
|
self.dtb.Sync(auto_resize=True)
|
|
|
|
def test_string_list(self):
|
|
"""Test adding string-list property to a node"""
|
|
val = ['123', '456']
|
|
self.node.AddStringList('stringlist', val)
|
|
self.dtb.Sync(auto_resize=True)
|
|
data = self.fdt.getprop(self.node.Offset(), 'stringlist')
|
|
self.assertEqual(b'123\x00456\0', data)
|
|
|
|
val = []
|
|
self.node.AddStringList('stringlist', val)
|
|
self.dtb.Sync(auto_resize=True)
|
|
data = self.fdt.getprop(self.node.Offset(), 'stringlist')
|
|
self.assertEqual(b'', data)
|
|
|
|
def test_delete_node(self):
|
|
"""Test deleting a node"""
|
|
old_offset = self.fdt.path_offset('/spl-test')
|
|
self.assertGreater(old_offset, 0)
|
|
self.node.Delete()
|
|
self.dtb.Sync()
|
|
new_offset = self.fdt.path_offset('/spl-test', libfdt.QUIET_NOTFOUND)
|
|
self.assertEqual(-libfdt.NOTFOUND, new_offset)
|
|
|
|
def testFromData(self):
|
|
dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
|
|
self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
|
|
|
|
self.node.AddEmptyProp('empty', 5)
|
|
self.dtb.Sync(auto_resize=True)
|
|
self.assertTrue(dtb2.GetContents() != self.dtb.GetContents())
|
|
|
|
def testMissingSetInt(self):
|
|
"""Test handling of a missing property with SetInt"""
|
|
with self.assertRaises(ValueError) as e:
|
|
self.node.SetInt('one', 1)
|
|
self.assertIn("node '/spl-test': Missing property 'one'",
|
|
str(e.exception))
|
|
|
|
def testMissingSetData(self):
|
|
"""Test handling of a missing property with SetData"""
|
|
with self.assertRaises(ValueError) as e:
|
|
self.node.SetData('one', b'data')
|
|
self.assertIn("node '/spl-test': Missing property 'one'",
|
|
str(e.exception))
|
|
|
|
def testMissingSetString(self):
|
|
"""Test handling of a missing property with SetString"""
|
|
with self.assertRaises(ValueError) as e:
|
|
self.node.SetString('one', 1)
|
|
self.assertIn("node '/spl-test': Missing property 'one'",
|
|
str(e.exception))
|
|
|
|
def testGetFilename(self):
|
|
"""Test the dtb filename can be provided"""
|
|
self.assertEqual(tools.get_output_filename('source.dtb'),
|
|
self.dtb.GetFilename())
|
|
|
|
|
|
class TestFdtUtil(unittest.TestCase):
|
|
"""Tests for the fdt_util module
|
|
|
|
This module will likely be mostly replaced at some point, once upstream
|
|
libfdt has better Python support. For now, this provides tests for current
|
|
functionality.
|
|
"""
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
tools.prepare_output_dir(None)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
tools.finalise_output_dir()
|
|
|
|
def setUp(self):
|
|
self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
|
|
self.node = self.dtb.GetNode('/spl-test')
|
|
|
|
def testGetInt(self):
|
|
self.assertEqual(1, fdt_util.GetInt(self.node, 'intval'))
|
|
self.assertEqual(3, fdt_util.GetInt(self.node, 'missing', 3))
|
|
|
|
with self.assertRaises(ValueError) as e:
|
|
fdt_util.GetInt(self.node, 'intarray')
|
|
self.assertIn("property 'intarray' has list value: expecting a single "
|
|
'integer', str(e.exception))
|
|
|
|
def testGetInt64(self):
|
|
self.assertEqual(0x123456789abcdef0,
|
|
fdt_util.GetInt64(self.node, 'int64val'))
|
|
self.assertEqual(3, fdt_util.GetInt64(self.node, 'missing', 3))
|
|
|
|
with self.assertRaises(ValueError) as e:
|
|
fdt_util.GetInt64(self.node, 'intarray')
|
|
self.assertIn(
|
|
"property 'intarray' should be a list with 2 items for 64-bit values",
|
|
str(e.exception))
|
|
|
|
def testGetString(self):
|
|
self.assertEqual('message', fdt_util.GetString(self.node, 'stringval'))
|
|
self.assertEqual('test', fdt_util.GetString(self.node, 'missing',
|
|
'test'))
|
|
self.assertEqual('', fdt_util.GetString(self.node, 'boolval'))
|
|
|
|
with self.assertRaises(ValueError) as e:
|
|
self.assertEqual(3, fdt_util.GetString(self.node, 'stringarray'))
|
|
self.assertIn("property 'stringarray' has list value: expecting a "
|
|
'single string', str(e.exception))
|
|
|
|
def testGetStringList(self):
|
|
self.assertEqual(['message'],
|
|
fdt_util.GetStringList(self.node, 'stringval'))
|
|
self.assertEqual(
|
|
['multi-word', 'message'],
|
|
fdt_util.GetStringList(self.node, 'stringarray'))
|
|
self.assertEqual(['test'],
|
|
fdt_util.GetStringList(self.node, 'missing', ['test']))
|
|
self.assertEqual([], fdt_util.GetStringList(self.node, 'boolval'))
|
|
|
|
def testGetArgs(self):
|
|
node = self.dtb.GetNode('/orig-node')
|
|
self.assertEqual(['message'], fdt_util.GetArgs(self.node, 'stringval'))
|
|
self.assertEqual(
|
|
['multi-word', 'message'],
|
|
fdt_util.GetArgs(self.node, 'stringarray'))
|
|
self.assertEqual([], fdt_util.GetArgs(self.node, 'boolval'))
|
|
self.assertEqual(['-n first', 'second', '-p', '123,456', '-x'],
|
|
fdt_util.GetArgs(node, 'args'))
|
|
self.assertEqual(['a space', 'there'],
|
|
fdt_util.GetArgs(node, 'args2'))
|
|
self.assertEqual(['-n', 'first', 'second', '-p', '123,456', '-x'],
|
|
fdt_util.GetArgs(node, 'args3'))
|
|
with self.assertRaises(ValueError) as exc:
|
|
fdt_util.GetArgs(self.node, 'missing')
|
|
self.assertIn(
|
|
"Node '/spl-test': Expected property 'missing'",
|
|
str(exc.exception))
|
|
|
|
def testGetBool(self):
|
|
self.assertEqual(True, fdt_util.GetBool(self.node, 'boolval'))
|
|
self.assertEqual(False, fdt_util.GetBool(self.node, 'missing'))
|
|
self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
|
|
self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
|
|
|
|
def testGetByte(self):
|
|
self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
|
|
self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
|
|
|
|
with self.assertRaises(ValueError) as e:
|
|
fdt_util.GetByte(self.node, 'longbytearray')
|
|
self.assertIn("property 'longbytearray' has list value: expecting a "
|
|
'single byte', str(e.exception))
|
|
|
|
with self.assertRaises(ValueError) as e:
|
|
fdt_util.GetByte(self.node, 'intval')
|
|
self.assertIn("property 'intval' has length 4, expecting 1",
|
|
str(e.exception))
|
|
|
|
def testGetBytes(self):
|
|
self.assertEqual(bytes([5]), fdt_util.GetBytes(self.node, 'byteval', 1))
|
|
self.assertEqual(None, fdt_util.GetBytes(self.node, 'missing', 3))
|
|
self.assertEqual(
|
|
bytes([3]), fdt_util.GetBytes(self.node, 'missing', 3, bytes([3])))
|
|
|
|
with self.assertRaises(ValueError) as e:
|
|
fdt_util.GetBytes(self.node, 'longbytearray', 7)
|
|
self.assertIn(
|
|
"Node 'spl-test' property 'longbytearray' has length 9, expecting 7",
|
|
str(e.exception))
|
|
|
|
self.assertEqual(
|
|
bytes([0, 0, 0, 1]), fdt_util.GetBytes(self.node, 'intval', 4))
|
|
self.assertEqual(
|
|
bytes([3]), fdt_util.GetBytes(self.node, 'missing', 3, bytes([3])))
|
|
|
|
def testGetPhandleList(self):
|
|
dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
|
|
node = dtb.GetNode('/phandle-source2')
|
|
self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
|
|
node = dtb.GetNode('/phandle-source')
|
|
self.assertEqual([1, 2, 11, 3, 12, 13, 1],
|
|
fdt_util.GetPhandleList(node, 'clocks'))
|
|
self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
|
|
|
|
def testGetDataType(self):
|
|
self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
|
|
self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
|
|
str))
|
|
with self.assertRaises(ValueError) as e:
|
|
self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
|
|
bool))
|
|
def testFdtCellsToCpu(self):
|
|
val = self.node.props['intarray'].value
|
|
self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
|
|
self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
|
|
|
|
dtb2 = fdt.FdtScan(find_dtb_file('dtoc_test_addr64.dts'))
|
|
node1 = dtb2.GetNode('/test1')
|
|
val = node1.props['reg'].value
|
|
self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
|
|
|
|
node2 = dtb2.GetNode('/test2')
|
|
val = node2.props['reg'].value
|
|
self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
|
|
self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
|
|
2))
|
|
self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
|
|
|
|
def testEnsureCompiled(self):
|
|
"""Test a degenerate case of this function (file already compiled)"""
|
|
dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'))
|
|
self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
|
|
|
|
def testEnsureCompiledTmpdir(self):
|
|
"""Test providing a temporary directory"""
|
|
try:
|
|
old_outdir = tools.outdir
|
|
tools.outdir= None
|
|
tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
|
|
dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'),
|
|
tmpdir)
|
|
self.assertEqual(tmpdir, os.path.dirname(dtb))
|
|
shutil.rmtree(tmpdir)
|
|
finally:
|
|
tools.outdir= old_outdir
|
|
|
|
|
|
def RunTestCoverage():
|
|
"""Run the tests and check that we get 100% coverage"""
|
|
test_util.run_test_coverage('tools/dtoc/test_fdt.py', None,
|
|
['tools/patman/*.py', '*test_fdt.py'], options.build_dir)
|
|
|
|
|
|
def RunTests(args):
|
|
"""Run all the test we have for the fdt model
|
|
|
|
Args:
|
|
args: List of positional args provided to fdt. This can hold a test
|
|
name to execute (as in 'fdt -t testFdt', for example)
|
|
|
|
Returns:
|
|
Return code, 0 on success
|
|
"""
|
|
test_name = args and args[0] or None
|
|
result = test_util.run_test_suites(
|
|
'test_fdt', False, False, False, None, test_name, None,
|
|
[TestFdt, TestNode, TestProp, TestFdtUtil])
|
|
|
|
return (0 if result.wasSuccessful() else 1)
|
|
|
|
|
|
if __name__ != '__main__':
|
|
sys.exit(1)
|
|
|
|
parser = OptionParser()
|
|
parser.add_option('-B', '--build-dir', type='string', default='b',
|
|
help='Directory containing the build output')
|
|
parser.add_option('-P', '--processes', type=int,
|
|
help='set number of processes to use for running tests')
|
|
parser.add_option('-t', '--test', action='store_true', dest='test',
|
|
default=False, help='run tests')
|
|
parser.add_option('-T', '--test-coverage', action='store_true',
|
|
default=False, help='run tests and check for 100% coverage')
|
|
(options, args) = parser.parse_args()
|
|
|
|
# Run our meagre tests
|
|
if options.test:
|
|
ret_code = RunTests(args)
|
|
sys.exit(ret_code)
|
|
elif options.test_coverage:
|
|
RunTestCoverage()
|